在Silverlight开发中,我们一直强调MVVM模式的好处。但很多时候,MVVM模式无法解决或者说很难解决 从ViewModel 到 View 的事件传递。(Event to Command)
使用这个家伙的MVVM Light 可以实现,但是要经过很多的波折。对此很多人也有争议:牺牲那么多时间去保持一个清洁干净的XAML意义是否有那么大?
我的这个例子要实现的内容:
1. 在主窗体(MainPage)按下DataGrid中绑定的按纽;
2.按钮把DataGrid中的产品编号传递到一个子窗体,子窗体启动,并可以显示(修改)这个产品编号;
3.按下保存,子窗体关闭,并把修改过的产品编号传递回主窗体(MainPage)。
4.主窗体刷新
我们知道:1,2,3 步骤用MVVM 是很好实现的,把按钮的命令通过ICommand传递到ViewModel执行,在ViewModel打开子窗体,并修改数据,没有问题。但如何通知主窗体刷新?我这里提到的不仅仅是刷新这个问题,可能还有其他的动作,比如数据更新后,更换主窗体的一张图片或改变主窗体某个控件的尺寸等等。
所以第4个步骤用MVVM是比较困难的。
如果我们直接把按钮绑定到主窗体的Code Behind中,就很好解决这个问题了。
主窗体DataGrid的代码:
<sdk:DataGrid x:Name="productGrid" Margin="50,50,55,40" AutoGenerateColumns="False" ItemsSource="{Binding}"> <sdk:DataGrid.Columns > <sdk:DataGridTemplateColumn Header="编辑产品" Width="Auto"> <sdk:DataGridTemplateColumn.CellTemplate > <DataTemplate > <!--MVVM的绑定模式--> <!--<Button Content="编辑" Command="{Binding RefreshEventsCommand, Source={StaticResource mViewModel}}" CommandParameter="{Binding ProductID}"/>--> <!--直接绑定Code Behind--> <Button Content="编辑" Click="button_Click" CommandParameter="{Binding ProductID}"/> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn> <sdk:DataGridTextColumn Header="产品编号" Width="SizeToHeader" Binding="{Binding ProductID}"/> <sdk:DataGridTextColumn Header="产品名称" Width="SizeToHeader" Binding="{Binding ProductName}"/> </sdk:DataGrid.Columns> </sdk:DataGrid>
主窗体 Code Behind 代码:
public partial class MainPage : UserControl { private string ProductID = string.Empty; public MainPage() { InitializeComponent(); this.productGrid.ItemsSource = new ExampleData().getProducts; } void cw__passproductid(string productid)//取得已经修改得ProductID { if (!string.IsNullOrEmpty(productid)) { MessageBox.Show("已经接收到修改得ProductID:" + productid); //接收到这个事件就可以刷新,或做其它事情了 //.... this.productGrid.ItemsSource = new ExampleData().getProducts; } } private void button_Click(object sender, RoutedEventArgs e) { string commandParameter = (string)((System.Windows.Controls.Primitives.ButtonBase)(sender)).CommandParameter; MessageBox.Show("已经接收到修改得ProductID:" + commandParameter); ChildWindow1 cw = new ChildWindow1(commandParameter); cw._passproductid += new PassProductID(cw__passproductid); cw.Show(); } }
直接通过绑定,在主窗体打开子窗体,通过委托事件,接收子窗体修改过的产品编号,控制权又回到了主窗体,
就可以做任何你想做的事情了,世界又一片清静了!
完成代码下载: http://www.dengfeng.org/soft/MVVM_PassCommand_dengfengsoft.zip