在前一篇介绍中简单实现了MVVM模式,这一篇中我想补充一下关于Event To Command的内容。
点击人的时候弹出框显示人的信息,这一功能主要用到了 GalaSoft.MvvmLight 中EventToCommand的CommandParameter属性,用它来绑定ListBoxItem的数据源并传回给相应的command。
以下是截图:
知识点:
1. 在前一篇文章中我提供了ContactsList.xaml的布局代码,代码里提供了Loaded事件对应的Command,这里的一个小小改动就是增加了ListBoxItem的SelectionChanged事件Command,以及如何将ListBoxItem对应的数据源(Person对象)传递给相应的Command。以下是相应的ContactsList.xaml代码改进部分
<ListBox DataContext="{StaticResource ContractsListViewModel}"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ItemTemplate}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel></toolkit:WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<i:Interaction.Triggers>
<!--对LstBox的loaded事件附加绑定命令,同样,
List的数据加载也可以在这个命令excute里进行,
然后将ItemsSource绑定到一个集合-->
<i:EventTrigger EventName="Loaded">
<lightToolkit:EventToCommand Command="{Binding LoadedCommand, Mode=OneWay}"></lightToolkit:EventToCommand>
</i:EventTrigger>
<!--对SelectionChanged事件提供Command,并将Item的数据源Person传递给Command-->
<i:EventTrigger EventName="SelectionChanged">
<lightToolkit:EventToCommand
Command="{Binding SelectionChanged, Mode=OneWay}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=SelectedItem}"
></lightToolkit:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
2. 做这个功能的时候我对Command的设计做了少许改进,
A.建立一个CommandBase
public class CommandBase:ICommand
{
Action<object> Excuted;
Func<object, bool> CanExcuted;
bool CanExcuteCache = false;
protected CommandBase(Action<object> excuted, Func<object, bool> canExcuted)
{
this.Excuted = excuted;
this.CanExcuted = canExcuted;
}
public bool CanExecute(object parameter)
{
bool tmp = this.CanExcuted(parameter);
if (this.CanExcuteCache != tmp)
{
this.CanExcuteCache = tmp;
if (this.CanExecuteChanged != null)
this.CanExecuteChanged(this, new EventArgs());
}
return tmp;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
this.Excuted.Invoke(parameter);
}
}
B. 实际的Command类型
public class UserSelectionChangedCommand : CommandBase
{
public UserSelectionChangedCommand(Action<object> excuted, Func<object, bool> canExcuted)
:base(excuted, canExcuted)
{
}
}
这样的设计使command的使用及维护更加灵活
3. 对应的VM()里对使用到的Command进行实例化,并提供相应的Command处理方法,下面是设计之后的实例化Command部分
public ContactsListViewModel()
{
this.LoadedCommand = new ShowMessageCommand(this.DoWorkOnLoaded, this.CanExcute);
this.SelectionChanged = new UserSelectionChangedCommand(this.UserSelectionChanged, this.CanExcute);
}
public ShowMessageCommand LoadedCommand { get; private set; }
public UserSelectionChangedCommand SelectionChanged { get; private set; }
#region Commands
void DoWorkOnLoaded(object str)
{
System.Diagnostics.Debug.WriteLine("loaded>>>> " + DateTime.Now.ToShortDateString());
}
bool CanExcute(object parameter)
{
return true;
}
void UserSelectionChanged(object obj)
{
Person p = obj as Person;
MessageBox.Show("you choose: " + p.Name + " " + p.Tel);
}
#endregion
4. 源码下载