2014-09-19 83 views
0

一個新手問題,但我不能得到它的工作。在嘗試使用答案SO "How Should the View Model Close the form" ,我有一個用戶控件與定義:無法使用附加屬性(MVVM)關閉模式對話框?

其在設計節目
<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(); 

在視圖模型的用戶控件,我有:

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

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

使用DoExit(),模態對話框,我的用戶,確實接近。怎麼了?我如何讓設計師(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(); 
    } 
} 

注:如果 「用戶控件」 的,而不是作爲一個 「窗口」 時,設計師是幸福的,但隨後的錯誤是:

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

幫助別人?

+0

這段代碼從哪裏來??'var win = new WindowDialog();' – Sheridan 2014-09-19 13:27:35

+0

@Sheridan在另一個視圖模型(另一個用戶控件)中。 – 2014-09-19 13:28:47

+0

如果它包含該代碼,那麼它不是視圖模型。視圖模型不應該知道關於'窗口'和視圖的*任何*。在這種情況下,無論如何你的'視圖模型'被破壞,只要正常處理'Window.Close':'if(win.ShowDialog()== DialogResult.OK)DoSomething();' – Sheridan 2014-09-19 13:32:41

回答

2

我對此很陌生,但把所有東西放在一起,我建議這可以作爲像我這樣的新手的一個可能的答案。

這是否符合最佳MVVM實踐?

首先,設計師指出,「物業‘的DialogResult’不附接到型‘用戶控件’的元素

我的翻譯,一個‘控’是不是一個窗口 - 所以它不能被關閉因此,

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

是錯誤的,請將其刪除。

其次,我的用戶被顯示爲原本平面窗口的唯一元素

<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) 
           { 
           } 
        } 
       ); 
     }; 

當在用戶控件上單擊退出,它通過其視圖模型中的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(視圖模型),然後調用返回到最上面的視圖模型和完成與

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

因此完成了幾個激烈的學習時間。我希望它對某人有用。