2013-07-20 78 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}"/>