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\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.