2013-07-20 73 views
0

保持MVVM記住什麼纔是打開子窗口的正確方法(例如,修改主窗口上的選定項)?將複雜對象傳遞給子窗口

這是我有:MainWindow.xaml(在MainWindow.xaml.cs它分配MainVM作爲自己的DataContext)

我也想有:ChildWindow.xaml和準系統ChildWindow.xaml.cs與ChildVM隱藏在控件之後。

所以,現在:

  1. 我怎麼能彈出ChildWindow並傳遞一些對象DataChildVM
  2. 將結果(true/false)和結果數據(一些複雜的 對象)返回到MainVM
  3. 作爲獎勵,可以在Data的變化 的MainVM,而他們在ChildVM的工作?

這是我試過的 - 它並不能解決所有問題,但這是否正確?

  • 對於(2),I創建的Window一個子類,稱爲DialogWindow,其具有3個DependencyProperties:Data(用於輸入數據),ResultData(輸出數據)和ResultValue(爲一個布爾結果)。
  • ResultDataResultValue均由的DialogWindowChildVM使用綁定集,並且當ResultValue被設置時,DialogWindow關閉。
  • 目前,ChildWindow從MainWindow.xaml.cs啓動(所有意圖和目的) - 有點不好。那麼我可以通過一些輸入數據,像這樣:

    ChildDialogWindow w = new ChildDialogWindow();

    w.Data = myDataObj;

所以,現在我需要有一個屬性Data上ChildVM,並在ChildDialogWindow.xaml.cs設置。再一次,使.xaml.cs更厚。

我認爲,避免MainWindow.xaml.cs可能是一種更好的方法DialogService作爲依賴傳遞給MainVM。但是,如何將值傳遞給ChildVM

+1

[也許看看這個?](http://stackoverflow.com/a/16994523/1834662) – Viv

+0

@Viv,這是不壞,但它採用的是框架,我希望避免。我想也許我可以解除Messenger的代碼(除非它依賴於其他一些框架,比如SimpleIoC) –

+0

爲什麼要避免使用框架?.net是一個框架,我們可以編寫本機C代碼並避免.net all-together :)如果你的目的是要「學習」它的功能,你可以隨時獲得它的源代碼,看看它是如何實現的,並且自己做。 'SimpleIoC'只是一個非常簡單的DI容器。如果你正在尋找廣泛的功能,你會看Unity並分類。我只是爲了「不依賴」而重新發明車輪。 – Viv

回答

1

試試這個。 進行對話服務。CS

public class DialogService 
{ 
    public void Show(FrameworkElement view, ChildViewModel ChildVM) 
    { 
     Window window = new Window(); 
     window.Content = view; 
     window.DataContext = ChildVM; 

     // For closing this dialog using MVVM 
     ChildVM.RequestClose += delegate 
     { 
      window.Close(); 
     }; 

     window.Show(); 
    } 
} 

現在ChildVm類,添加此

public ICommand CloseCommand 
    { 
     get 
     { 
      if (_closeCommand == null) 
       _closeCommand = new RelayCommand(param => this.OnRequestClose()); 

      return _closeCommand; 
     } 
    } 

    public event EventHandler RequestClose; 

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

現在,這種方式推出這款

public void OpenChildDailog() 
    { 
    DialogService service = new DialogService(); 
    ChildViewModel childVM = new ChildViewModel(); 
    childVM.Data = ; // Assign whatever you want 
    childVM.ResultData = ; 

    service.Show(new ChildView(), childVM); 

    // Now get the values when the child dailog get closed 

    var retVal = childVM.ResultValue; 

} 
+0

謝謝。 ChildView是一個UserControl嗎?我有ChildWindow.xaml/.xaml.cs ...你是否放棄使用UserControl?另外...在你的例子中,service.Show()會立即返回,所以childVM.ResultValue不會被設置。 –

+0

是的在這種情況下,ChildView應該是一個用戶控件。 service.Show()不會立即返回。它會打開窗口並保持打開狀態,直到用戶關閉它,然後它將返回到下一行,即var retVal = childVM.ResultValue;'。確保提供了在ChildViewModel中設置ResultValue的邏輯,以便在從對話框關閉返回時填充它。 – UsmanAzam

+1

[Window.Show()](http://msdn.microsoft.com/en-us/library/system.windows.window.show.aspx)立即返回...但它至少應該起作用, 'ShowDialog()'...謝謝 –

0

我使用的ICommand幫手 「RelayCommand,」 和推一個IntPtr數據類型到新的ViewModel(或使用任何其他對象)。很多cookie工具的東西。

主視圖:

<Button Command="{Binding DataContext.ShowObjectInfoCommand}" CommandParameter="{Binding ObjectOffset}" Content="{Binding Name}"/> 

MainViewModel:

private RelayCommand _showObjectInfoCommand; 
public RelayCommand ShowObjectInfoCommand { get { return _showObjectInfoCommand ?? (_showObjectInfoCommand = new RelayCommand(ExeShowObjectInfoCommand)); } set { } } //Draw Specific Item Table 
void ExeShowObjectInfoCommand(object parameter) 
{ 
    ViewObjectInfo objInfo = new ViewObjectInfo(); 
    IObjectOffsetParameter viewModel = objInfo.DataContext as IObjectOffsetParameter; 
    viewModel.ObjectOffset = (IntPtr)parameter; 
    objInfo.Show(); 
} 

新視圖模型+接口:

interface IObjectOffsetParameter 
{ 
    IntPtr ObjectOffset { get; set; } 
} 

class ViewModelObjectInfo : ViewModelBase, IObjectOffsetParameter 
{ 
    public ViewModelObjectInfo() 
    { 
    } 

    private IntPtr _objectOffset; //Entity Offset 
    public IntPtr ObjectOffset 
    { 
     get { return _objectOffset; } 
     set { if (_objectOffset != value) { _objectOffset = value; RaisePropertyChanged("Offset"); } } 
    } 
} 

新視圖代碼隱藏:

InitializeComponent(); 
ViewModelObjectInfo viewModel = new ViewModelObjectInfo(); 
this.DataContext = viewModel; 

新視圖XAML:

<TextBlock Text="{Binding ObjectOffset}"/>