4
\$\begingroup\$

I am building a Metro-themed WPF application with MVVM approach using Prism and MahApps.Metro. I have to show a custom dialog from view model. Currently, I am using InteractionRequest and a custom TriggerAction to accomplish it, but I don't know if this is a good way.

MainWindow.xaml

<Controls:MetroWindow
    x:Class="Dialog.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:prism="http://www.codeplex.com/prism"
    xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
    xmlns:local="clr-namespace:Dialog"
    AllowsTransparency="False"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <ResourceDictionary>
            <Dialog:CustomDialog Title="MyTitle" x:Key="MyDialog">
                <Button Content="Close" Command="{Binding CloseCommand}"/>
            </Dialog:CustomDialog>
        </ResourceDictionary>
    </Window.Resources>

    <i:Interaction.Triggers>
        <prism:InteractionRequestTrigger SourceObject="{Binding ShowDialogRequest, Mode=OneWay}">
            <local:ShowDialogAction DataContext="{Binding DialogViewModel}" DialogKey="MyDialog"/>
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers>
    ...
</Controls:MetroWindow>

ShowDialogAction

public class ShowDialogAction : TriggerAction<MetroWindow>
{
    public static readonly DependencyProperty DataContextProperty =
        DependencyProperty.Register(
            "DataContext",
            typeof(object),
            typeof(ShowDialogAction),
            new PropertyMetadata(null));

    public static readonly DependencyProperty DialogKeyProperty =
        DependencyProperty.Register(
            "DialogKey",
            typeof(string),
            typeof(ShowDialogAction),
            new PropertyMetadata(null));

    public object DataContext
    {
        get { return this.GetValue(DataContextProperty); }
        set { this.SetValue(DataContextProperty, value); }
    }

    public string DialogKey
    {
        get { return (string)this.GetValue(DialogKeyProperty); }
        set { this.SetValue(DialogKeyProperty, value); }
    }

    protected async override void Invoke(object parameter)
    {
        InteractionRequestedEventArgs args = parameter as InteractionRequestedEventArgs;
        if (args == null)
        {
            return;
        }

        BaseMetroDialog dialog = AssociatedObject.Resources[DialogKey] as BaseMetroDialog;
        if (dialog == null)
        {
            return;
        }
        dialog.DataContext = DataContext;

        IInteractionRequestAware interactionAware = DataContext as IInteractionRequestAware;
        if(interactionAware != null)
        {
            interactionAware.Notification = args.Context;
            interactionAware.FinishInteraction = () =>
            {
                if (AssociatedObject.Dispatcher.CheckAccess())
                {
                    AssociatedObject.HideMetroDialogAsync(dialog);
                }
                else
                {
                    AssociatedObject.Dispatcher.Invoke(async () => await AssociatedObject.HideMetroDialogAsync(dialog));
                }
            };
        }

        await AssociatedObject.ShowMetroDialogAsync(dialog);
    }

DialogViewModel

public class DialogViewModel : BindableBase, IInteractionRequestAware
{
    public Action FinishInteraction { get; set; }

    public INotification Notification { get; set; }

    private ICommand closeCommand;
    public ICommand CloseCommand
    {
        get
        {
            return this.closeCommand ?? (this.closeCommand = new DelegateCommand(FinishInteraction));
        }
    }
}

I have several questions:

  1. Which is better, using a resource key or explicitly setting a Dialog property for ShowDialogAction accepting a CustomDialog?
  2. Is there any better alternatives to pass/create a DialogViewModel to the dialog?
  3. Is the FinishInteraction okay? I am not too familiar with async/await.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.