当用户双击列表项时,我试图使用附加行为在ViewModel中执行命令。
我已经阅读了许多有关该主题的文章,并尝试创建一个简单的测试应用程序,但是仍然存在一些问题,例如。
Firing a double click event from a WPF ListView item using MVVM
我的简单测试ViewModel有2个集合,一个集合返回字符串列表,另一个集合返回ListViewItem类型的列表
public class ViewModel
{
public ViewModel()
{
Stuff = new ObservableCollection<ListViewItem>
{
new ListViewItem { Content = "item 1" },
new ListViewItem { Content = "item 2" }
};
StringStuff = new ObservableCollection<string> { "item 1", "item 2" };
}
public ObservableCollection<ListViewItem> Stuff { get; set; }
public ObservableCollection<string> StringStuff { get; set; }
public ICommand Foo
{
get
{
return new DelegateCommand(this.DoSomeAction);
}
}
private void DoSomeAction()
{
MessageBox.Show("Command Triggered");
}
}
这是附加的属性,就像您看到的其他示例一样:
public class ClickBehavior
{
public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached("DoubleClick",
typeof(ICommand),
typeof(ClickBehavior),
new FrameworkPropertyMetadata(null, new PropertyChangedCallback(ClickBehavior.DoubleClickChanged)));
public static void SetDoubleClick(DependencyObject target, ICommand value)
{
target.SetValue(ClickBehavior.DoubleClickCommandProperty, value);
}
public static ICommand GetDoubleClick(DependencyObject target)
{
return (ICommand)target.GetValue(DoubleClickCommandProperty);
}
private static void DoubleClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
ListViewItem element = target as ListViewItem;
if (element != null)
{
if ((e.NewValue != null) && (e.OldValue == null))
{
element.MouseDoubleClick += element_MouseDoubleClick;
}
else if ((e.NewValue == null) && (e.OldValue != null))
{
element.MouseDoubleClick -= element_MouseDoubleClick;
}
}
}
static void element_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
UIElement element = (UIElement)sender;
ICommand command = (ICommand)element.GetValue(ClickBehavior.DoubleClickCommandProperty);
command.Execute(null);
}
}
在主窗口中,我定义了用于设置附加行为并绑定(bind)到Foo命令的样式。
<Window.Resources>
<Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="local:ClickBehavior.DoubleClick" Value="{Binding Foo}"/>
</Style>
</Window.Resources>
定义ListViewItems时工作正常:
<!-- Works -->
<Label Grid.Row="2" Content="DoubleClick click behaviour:"/>
<ListView Grid.Row="2" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}">
<ListViewItem Content="Item 3" />
<ListViewItem Content="Item 4" />
</ListView>
当绑定(bind)到类型为ListViewItem的列表时,这也可以工作:
<!-- Works when items bound are of type ListViewItem -->
<Label Grid.Row="3" Content="DoubleClick when bound to ListViewItem:"/>
<ListView Grid.Row="3" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding Stuff}">
</ListView>
但这不是:
<!-- Does not work when items bound are not ListViewItem -->
<Label Grid.Row="4" Content="DoubleClick when bound to string list:"/>
<ListView Grid.Row="4" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding StringStuff}">
</ListView>
在输出窗口中,您会看到错误,但发现很难理解错误所在。
System.Windows.Data错误:39:BindingExpression路径错误:在'object''String'(HashCode = 785742638)'上找不到'Foo'属性。 BindingExpression:Path = Foo; DataItem ='String'(HashCode = 785742638);目标元素是'ListViewItem'(Name ='');目标属性为“DoubleClick”(类型为“ICommand”)
所以我的问题是:将ListView绑定(bind)到Model对象列表时,如何正确地将Command连接到每个ListViewItem?
谢谢。
最佳答案
问题是DataContext
的Binding
是字符串。由于字符串类没有Foo
属性,因此会出现错误。在其他情况下,则不会发生这种情况,因为它们从父级那里继承了DataContext
(对于自动生成的数据项容器,这种情况不会发生-它们的DataContext
是数据项)。
如果将绑定(bind)更改为使用父ListView
的DataContext
,则应该可以正常工作:
Value="{Binding DataContext.Foo, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
关于c# - 附加行为以执行ListViewItem的命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4629862/