A good aproach to events in MVVM
So I ran into this problem trying to implement MVVM. AFAIK the best way to execute a method in the ViewModel class is through a CommandBinding.
<Button Command={Binding DoSomethingCommand} />
Only this time I need to do something on a ListBoxItem double click, and the ListBoxItem doesn't implement ICommandSource. So I'm wondering what's the best approa开发者_如何学Goch to do this, if there is one.
Thanks!
Edit:
I just thought of a way, but it seems rather hacky. What if I expose the ListBox.DoubleClick event, and my ViewModel class subscribes to it and runs the correct method when the DoubleClick is fired?
You could handle the event in the code-behind file and call the method on the ViewModel object. In my opinion this is a lot better than starting to hack. :-) I won’t pass a WPF routed event to a ViewModel object.
Who says that code-behind is forbidden? The Model-View-ViewModel pattern definitely not.
You can used attached behaviors.
See here: http://geekswithblogs.net/HouseOfBilz/archive/2009/05/29/adventures-in-mvvm-ndash-commanding-with-list-boxes.aspx
Silverlight doesn't contain a Command button like the Button in WPF. The way we get around it there is to create a custom control that contains a command and maps that event to the command. Something like this should work.
public class CommandListBoxItem : ListBoxItem
{
public CommandListBoxItem()
{
DoubleClick += (sender, e) =>
{
if (Command != null && Command.CanExecute(CommandParameter))
Command.Execute(CommandParameter);
};
}
#region Bindable Command Properties
public static DependencyProperty DoubleClickCommandProperty =
DependencyProperty.Register("DoubleClickCommand",
typeof(ICommand), typeof(CommandListBoxItem),
new PropertyMetadata(null, DoubleClickCommandChanged));
private static void DoubleClickCommandChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
{
var item = source as CommandListBoxItem;
if (item == null) return;
item.RegisterCommand(args.OldValue as ICommand, args.NewValue as ICommand);
}
public ICommand DoubleClickCommand
{
get { return GetValue(DoubleClickCommandProperty) as ICommand; }
set { SetValue(DoubleClickCommandProperty, value); }
}
public static DependencyProperty DoubleClickCommandParameterProperty =
DependencyProperty.Register("DoubleClickCommandParameter",
typeof(object), typeof(CommandListBoxItem),
new PropertyMetadata(null));
public object DoubleClickCommandParameter
{
get { return GetValue(DoubleClickCommandParameterProperty); }
set { SetValue(DoubleClickCommandParameterProperty, value); }
}
#endregion
private void RegisterCommand(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null)
oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;
if (newCommand != null)
newCommand.CanExecuteChanged += HandleCanExecuteChanged;
HandleCanExecuteChanged(newCommand, EventArgs.Empty);
}
private void HandleCanExecuteChanged(object sender, EventArgs args)
{
if (DoubleClickCommand != null)
IsEnabled = DoubleClickCommand.CanExecute(DoubleClickCommandParameter);
}
}
Then when you create your ListBoxItems you bind to the new Command Property.
<local:CommandListBoxItem DoubleClickCommand="{Binding ItemDoubleClickedCommand}" />
精彩评论