执行 ListViewItem 命令的附加行为

2024-01-12

当用户双击列表项时,我尝试使用附加行为在我的 ViewModel 中执行命令。

我已经审阅了有关该主题的许多文章,并尝试创建一个简单的测试应用程序,但仍然遇到问题,例如。使用 MVVM 从 WPF ListView 项目触发双击事件 https://stackoverflow.com/questions/1035023/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);
    }
}

在我的主窗口中,我定义了设置附加行为并绑定到 Foo 命令的样式

<Window.Resources>
    <Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="local:ClickBehavior.DoubleClick" Value="{Binding Foo}"/>                 
    </Style>
</Window.Resources>

定义 ListView 项目时工作正常:

<!-- 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>

当绑定到 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 路径错误:在“对象”“字符串”(HashCode=785742638) 上找不到“Foo”属性。 BindingExpression:Path=Foo; DataItem='字符串' (HashCode=785742638);目标元素是“ListViewItem”(名称=“”);目标属性是“DoubleClick”(类型“ICommand”)

所以我的问题是:当您将 ListView 绑定到 Model 对象列表时,如何将 Command 正确连接到每个 ListView Item?

Thanks.


问题是DataContext为了Binding是字符串。既然没有Foo字符串类的属性,您将收到错误。这在其他情况下不会发生,因为它们继承了它们的DataContext来自父级(对于自动生成的数据项容器,不会发生这种情况 - 它们的DataContext是数据项)。

如果您更改绑定以使用父级ListView's DataContext,它应该可以正常工作:

Value="{Binding DataContext.Foo, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

执行 ListViewItem 命令的附加行为 的相关文章

随机推荐