管窥MVVMLight Command参数绑定和事件传递

摘要:
主页面。Xaml是我们的视图页面。下面,我们将使用示例演示MVVM模式如何在MvvmLightToolkit中实现,如何绑定命令,以及如何传输事件消息。首先,在此框架中,MVVM模式的入口点是ViewModelLocator类。在该类中,可以定义多个ViewModel属性,并且可以通过ServiceLocator定义每个属性。当前GetInstance方法被映射以便于暴露到前台绑定。映射后,将显示ViewModel对象。它需要从ViewModelBase类继承,该类封装ICommand、INotifypropertyChanged和其他接口,使其易于使用。

前言

由于在实际项目中,业务功能的增加导致软件开发规模在逐渐变大,所以我准备找个Silverlight框架来组织当前项目中的文件,以期能够让后续的业务功能增添和维护更加容易一些。无意中,我在这篇文章中看到了当前Silverlight下所有的框架的评测:Discover and compare existing MVVM frameworks !,当我看到MvvmLight toolkit在各方面都比较完备的时候,于是决定选择这个框架:

image

Codeplex网站上,下载了MVVM Light Toolkit V4 RTM这个版本,因为我用的是vs2010,所以我下载了支持当前机器IDE的版本。

新建项目,选择MvvmLight(SL4),之后我们就可以看到项目结构了:

image

其中:

Design文件夹中的文件主要提供设计时运行支持

Model文件夹则放置了富实体模型

Skins文件夹则放置了样式文件定义

ViewModel文件夹则放置了ViewModel对象,其实MainViewModel和MainPage是一对一的(ViewMoel-View)关系.二者的映射通过ViewModelLocator进行。

MainPage.xaml就是我们的视图页面

下面我们就以例子来演示MvvmLight Toolkit中是如何实现MVVM模式,如何绑定命令,如何进行事件消息传递的。

首先,在这个框架中,MVVM模式的入口点为ViewModelLocator类,在这个类中,可以定义多个ViewModel属性,并且每个属性都可以通过ServiceLocator.Current.GetInstance方法进行映射,以便于暴露给前台绑定。同时,在新增一个ViewModel类的时候,一定要在其提供的SimpleIoc对象容器中进行注册,以便于能够通过IOC的方式获取其实例。

做完映射后,就是我们的ViewModel对象了。它需要继承自ViewModelBase类,这个类封装了ICommand,INotifypropertyChanged等接口,使用起来很方便。比如可以用RaisePropertyChanged直接来抛出变更通知。

之后就是View了,在View中,我们需要先对DataContext进行绑定:

DataContext="{Binding Main, Source={StaticResource Locator}}"

然后就可以随心所欲的操作了。

然后,我们来讲解下绑定命令。

由于命令绑定是应用程序中必不可少的环节,所以这里我以 绑定无参事件,绑定一个参数事件,绑定多个参数事件来说明。

绑定无参事件:

  #region Command without parameters
        private RelayCommand showText;
        public RelayCommand ShowText
        {
            get
            {
                if (showText == null)
                    showText = new RelayCommand(ShowTextFunc);
                return showText;
            }
        }
        public RelayCommand PassEvent { get; set; }
        
        private void ShowTextFunc()
        {
            MessageBox.Show("I am RealyCommand!");
        }
        #endregion

上面代码就是绑定无参事件,在View上可以通过如下方式绑定:

 <Button Content="绑定无参事件" 
 		 Command="{Binding ShowText}" 
		   
		 HorizontalAlignment="Left" 
		 Margin="32,62,0,0" 
		 Name="button1" 
		 VerticalAlignment="Top" 
		   />

绑定一个参数事件:

 #region Command with a parameter 
        private RelayCommand<int> showValue;
        public RelayCommand<int> ShowValue
        {
            get
            {
                if (showValue == null)
                    showValue = new RelayCommand<int>(x=>ShowValueFunc(x));
                return showValue;
            }
        }

        private int ShowValueFunc(int a)
        {
            int c = a + 10;
            MessageBox.Show(c.ToString());
            return c;
        }
        #endregion

上面的代码部分就是绑定一个参数的事件定义,我们来驱动view层:

<Button Content="绑定一个参数事件" 
        Command="{Binding ShowValue}" 
		CommandParameter="{Binding ElementName=textBox1,Path=Text,Converter={StaticResource IntConverter}}" 
		  
		HorizontalAlignment="Left" 
		Margin="32,103,0,0" 
		Name="button2" 
		VerticalAlignment="Top" 
		  />

需要说明的是,上面代码示例中,CommandParameter的值来自于textBox1的Text属性中。这个值加上10以后返回。

如果遇到用户输入不是数字的情况,则通过IntConverter方法将用户输入格式化,然后返回:

public class IntConverter:IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int result;
            if(Int32.TryParse(value.ToString(),out result))
            {
                return result;
            }
            return "0";
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

绑定多个参数事件:

由于RelayCommand默认最多允许一个参数传递,所以这里如果想传递多个数据对象,只能够去构建自己的DTO了。

在Model文件夹新建一个BookItem类:

public class BookItem
    {
        public string BName { get; set; }
        public string BAuthor { get; set; }
    }

然后在ViewModel中进行如下控制:

 #region Command with multiple parameters
        private RelayCommand<BookItem> showBooks;
        public RelayCommand<BookItem> ShowBooks
        {
            get
            {
                if (showBooks == null)
                    showBooks = new RelayCommand<BookItem>(x=>ShowBooksFunc(x));
                return showBooks;
            }
        }

        private void ShowBooksFunc(BookItem bookItem)
        {
            MessageBox.Show(bookItem.BName+"|"+bookItem.BAuthor);
        }
        #endregion

驱动View层:

 <Button Command="{Binding ShowBooks}"  
         Content="绑定多个参数事件" 
		   
		 HorizontalAlignment="Left" 
		 Margin="32,141,0,0" 
		 Name="button3" 
		 VerticalAlignment="Top" 
		   >
            <Button.CommandParameter>
                <model:BookItem BName="testName" BAuthor="TestAuthor" ></model:BookItem>
            </Button.CommandParameter>
 </Button>

运行起来得时候,我们发现BookItem参数已经被自动赋值了。

ViewModel之间事件传递

最后需要讲解的是如何在ViewModel之间进行事件传递。由于在MVVMLight Toolkit中已经集成了Messenger对象,所以我们可以利用其很方便的进行事件传递,下面新建一个ChildWindow1.xaml子窗体,然后在ViewModelLocator中添加如下代码:

 public ChildViewModel Child
        {
            get
            {
                return ServiceLocator.Current.GetInstance<ChildViewModel>();
            }
        }
SimpleIoc.Default.Register<ChildViewModel>();

然后在ViewModel文件夹中新建一个ChildViewModel类,在其中添加如下代码:

 public class ChildViewModel:ViewModelBase
    {
        public ChildViewModel()
        {
            Messenger.Default.Register<BookItem>(this, message =>
            {
                MyText = message.BName + "|" + message.BAuthor;
            });
        }
        public string MyText { get; set; }
    }

由于我们传递的对象是从 MainViewModel到ChildViewModel,所以我们在MainViewModel中添加如下发送代码:

 #region Messenger communication cross page
        private RelayCommand showChildWindow;
        public RelayCommand ShowChildWindow
        {
            get
            {
                if (showChildWindow == null)
                    showChildWindow = new RelayCommand(ShowChildWindowFunc);
                return showChildWindow;
            }
        }

        private void ShowChildWindowFunc()
        {
            ChildWindow1 child = new ChildWindow1();
            child.Show();
            var bookItem = new BookItem() { BAuthor="TestAuthor",BName="TestName" };
            Messenger.Default.Send<BookItem>(bookItem);
        }
        #endregion

这样当运行起来的时候,我们就能看到效果了:

image

好了,暂时就到这里,后面我们再深入挖掘。

百度网盘下载

腾讯微盘下载

免责声明:文章转载自《管窥MVVMLight Command参数绑定和事件传递》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇External Tools数据可视化之DAX篇(二十八)Power BI时间序列分析用到的度量值,一次全给你下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

ArcGIS地图打印设置

业务流程是首先框定要打印的地图范围,这是一个自定义大小。选择帧后,预览帧,然后选择打印输出。在打印输出界面中设置后,HP绘图仪将打印地图。因此,确定该问题与ArcGIS无关,属于打印地图设置问题。...

小米路由器3-R3 刷固件

3-3、大功告成,实测:带机12台,内存占用100MB、CPU使用20%不到满载200M带宽。...

Idea常用插件整合

官方网站:https://plugins.jetbrains.com/plugin/228-sql-query-plugin6.IdeaVim基于IntelliJ的Vim仿真插件。注意:如果打开WebInspector,那么CSS/JavaScript同步和元素高亮显示不起作用“pluginisdebuggingthistab”信息栏的可用性问题官方网站:h...

plsql 导出查询结果

单击青色按钮,表示所查询的所有数据都将导出到指定文件,而不仅仅是以下列表中显示的数据行;无需单击“获取最后一页”按钮。注意:选择导出到excel文件时,需要注意默认导出为*。xlsx格式。您可以选择*。xls格式,但*。xls格式只能容纳65536行数据。如果要导出的数据超过最大值,则必须更改为*。xlsx格式!如果您仍然使用此格式,后面的数据将覆盖以前的数...

element-ui表格el-table回显时默认全选数据

1、html代码˂el-table-columntype="selection"width="45"...

Matlab自定义函数的五种方法 [转]

子函数lfg2只能被主函数和主函数中的其他子函数调用。特点是,它是基于Matlab的数值运算内核的,所以它的运算速度较快,程序效率更高。...