C# WPF:将列表视图左键单击绑定到数据项命令



考虑这个 xaml :

<ListView ItemsSource="{Binding Items}" PreviewMouseLeftButtonDown="{Binding CheckItemCommand}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.Header>
<CheckBox IsThreeState="True" 
IsChecked="{Binding IsSelectAll, Mode=TwoWay}"
Command="{Binding CheckAllCommand}">
</CheckBox>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate DataType="x:MyObject">
<Grid>
<TextBlock Text="{Binding LoadingState}"/>
<CheckBox IsThreeState="False" 
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Command="{Binding CheckItemCommand}">
</CheckBox>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{Binding MyObject.Header_Name}"  
DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="{Binding MyObject.Header_CreationDate}" 
DisplayMemberBinding="{Binding CreationDate}" />
<GridViewColumn Header="{Binding MyObject.Header_NumberOfStuff1}"
DisplayMemberBinding="{Binding stuff1}"/>
<GridViewColumn Header="{Binding MyObject.Header_NumberOfStuff2}" 
DisplayMemberBinding="{Binding stuff2}"/>
</GridView>
</ListView.View>
</ListView>

我想调用 CheckItemCommand,当我单击行上的任意位置时,它已经绑定在行复选框上。

如何指定单击的行

PreviewMouseLeftButtonDown="{Binding CheckItemCommand}"

我找到了一些有效的东西。我对这个解决方案不是很满意,但它工作正常,它非常容易理解,可以用非常 fiew 代码( => KISS 原则)来完成。

为了获得正确的"OnRowClick => DoStuff()"行为,我拦截所有左键单击,然后,如果源类型正确,我调用Command_Execute()方法。

法典:

public MyContainer()
{
InitializeComponent();
this.PreviewMouseDown += MyContainer_PreviewMouseDown;
}
private void MyContainer_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var source = e.OriginalSource as FrameworkElement;
var dataContext = source?.DataContext;
if(dataContext.GetType() == typeof(ProperViewModel))
{
((ProperViewModel)dataContext).Command_Execute();
}
}

我很遗憾没有原生方法可以通过纯粹的命令模式来做到这一点......

如果有人有更好的方法,请随时提出另一个更优雅的答案

您可以使用交互触发器:

<ListView ItemsSource="{Binding Items}"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown" >
<i:InvokeCommandAction Command="{Binding CheckItemCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
...
</ListView>

EventTrigger在 Blend SDK 的一部分System.Windows.Interactivity.dll中定义:Visual Studio 2017 - 表达式交互发生了什么变化?

有关详细信息,请参阅以下博客文章:https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/。

我会使用鼠标绑定而不是事件。 使用样式应用:

当您单击一行时,您将使其成为所选项目,以便您可以使用它。或者也许不是,因为我看到你已经在那里进行了一些选择。

<Style TargetType="ListViewItem">
<Setter Property="local:AddToInputBinding.Binding">
<Setter.Value>
<MouseBinding Gesture="LeftClick" Command="{Binding YourCommand}" />    
</Setter.Value>
</Setter>

用于命令的代码可以使用绑定到 selecteditem 的属性。 如果这不适合,则可以使用命令参数来提供单击的项目。 我认为这看起来像:

CommandParameter="{Binding}"

这将为您提供该行作为数据上下文的整个对象 - 来自 Items 的项目。 如果您的命令不在列表视图中呈现给每个项目的任何对象中,则有点复杂。 您需要查找列表视图的数据上下文(而不是鼠标绑定最终将"进入"的行)。 使用相对源执行此操作。 该方面将如下所示:

Command="{Binding DataContext.YourCommand, 
RelativeSource={RelativeSource  
AncestorType={x:Type ListView}}}"

我不只是为你做这件事,而是试图解释所涉及的原则。 如果你不熟悉命令和参数,那么 mvvmlight 非常好,这篇关于 relaycommand 的文章可能会澄清: https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

最新更新