无法关闭附加属性(MVVM)的模态对话框?

时间:2014-09-19 13:17:52

标签: wpf mvvm user-controls modal-dialog attached-properties

一个新手问题,但我无法让它发挥作用。在尝试使用SO "How Should the View Model Close the form" 的答案时,我将UserControl定义为:

<UserControl 
         .....
         h:DialogCloser.DialogResult="{Binding DialogResult}"
         >

在设计时显示:

        Property 'DialogResult' is not attachable to elements of type 'UserControl'.

DialogCloser定义为:

         public static class DialogCloser
{
    public static readonly DependencyProperty DialogResultProperty =
        DependencyProperty.RegisterAttached(
            "DialogResult",
            typeof(bool?),
            typeof(DialogCloser),
            new PropertyMetadata(DialogResultChanged));

    private static void DialogResultChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        var window = d as Window;
        if (window != null)
            window.DialogResult = e.NewValue as bool?;
    }
    public static void SetDialogResult(Window target, bool? value)
    {
        target.SetValue(DialogResultProperty, value);
    }
}

UserControl由以下方式打开:

         var win = new WindowDialog();
         win.Title = title;
         win.DataContext = datacontext;

        return win.ShowDialog();

在UserControl的View Model中,我有:

public new void DoExit()
    {
        DialogResult = true;
    }

    private bool? dialogresult;
    public bool? DialogResult
    {
        get
        {
            return dialogresult;
        }
        set
        {
            if (dialogresult != value)
            {
                dialogresult = value;
                OnPropertyChanged("DialogResult");
            }
        }
    }

使用DoExit()时,模态对话框(我的UserControl) 关闭。怎么了?我如何让设计师(VS 2010)不抛出错误?

感谢您的帮助。

附录:

 public class ModalDialogService : IModalDialogService
{
     public bool? ShowDialog(string title, object datacontext)
    {
        var win = new WindowDialog();

        win.Title = title;
        win.DataContext = datacontext;

        return win.ShowDialog();
    }
}

注意:如果“UserControl”更像是“Window”,设计师很高兴,但错误是:

"Window must be the root of the tree. Cannot add Window as a child of Visual."

帮助某人?

1 个答案:

答案 0 :(得分:2)

我是新手,但把所有东西放在一起,我会建议这是像我这样的新手的可能答案。

这是否符合最佳MVVM做法?

首先,正如设计师所说&#34; Property&#39; DialogResult&#39;不能附加到&#39; UserControl&#39;。

类型的元素

我的翻译,&#34;控制&#34;不是一个窗口 - 因此它无法关闭。因此,

h:DialogCloser.DialogResult="{Binding DialogResult}"

错了。删除它。

其次,我的usercontrol被显示为另一个普通窗口的唯一元素

 <Window x:Class="Nova5.UI.Views.Ink.WindowDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowDialog" 
    WindowStyle="SingleBorderWindow" 
    WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">

    <ContentPresenter x:Name="DialogPresenter" Content="{Binding .}"/>

 </Window>

现在,当最顶层的视图模型

时,整个事情就会启动
   var dialog = new WindowDialog
            {
                Title = "It's me Margaret",
                ShowInTaskbar = false,               
                Topmost = true,                      
                ResizeMode = ResizeMode.NoResize    
            };
            dialog.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);

            ModalDialogService dialogService = new ModalDialogService();

            dialogService.ShowDialog<PrescriptionWriterViewModel>(dialog,
                new PrescriptionWriterViewModel(),
                returnedViewModelInstance =>                                
                    {
                            if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
                                {
                                 }
                     }
                );
        };

当在usercontrol上单击Exit时,它在其视图模型中通过DelegateCommand执行

 public new void DoExit()
    {
        OnRequestClose();
    }

    public event EventHandler RequestClose;

    void OnRequestClose()
    {
        EventHandler handler = this.RequestClose;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }

然后在启动对话服务

中处理此关闭请求
public void ShowDialog<TDialogViewModel>(IModalWindow view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose)
    {
        view.DataContext = viewModel;

        IDialogViewModel vm = viewModel as IDialogViewModel;
        if (vm !=null)
            vm.RequestClose += (s,e)=> view.Close();        //RequestClose is the event in the ViewModel that the view will listen for.

        if (onDialogClose != null)
        {
            view.Closed += (sender, e) => onDialogClose(viewModel);
        }               
        view.Show();
    }

当视图关闭时,onDialogClose(viewModel)然后回调到最顶层的视图模型并完成用

指定的操作
  returnedViewModelInstance =>                              
                    {
                            if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
                                {
                                 }
                     }

完成几个小时的学习。我希望它对某人有用。