使用 WPF + MVVM 中的 Command + CommandParameter 删除列表视图中的行

Posted

技术标签:

【中文标题】使用 WPF + MVVM 中的 Command + CommandParameter 删除列表视图中的行【英文标题】:Deleting row in listview using Command + CommandParameter in WPF + MVVM 【发布时间】:2011-10-21 01:06:34 【问题描述】:

我想使用 Command 和 CommandParameter 删除 ListView 控件中的一行,如下所示。

<GridViewColumn Header="X">
<GridViewColumn.CellTemplate>
    <DataTemplate>
        <StackPanel>
           <TextBlock Text="Binding CriteriaId"/>
           <Button Name="btnDeleteCriterion" Tag="Binding CriteriaId" Content="Binding CriteriaId" Foreground="Red" FontWeight="Bold" 
                                                             Command="Binding DeleteCriterionCommand" 
                                                                        DataContext="Binding DataContext, RelativeSource=RelativeSource FindAncestor, AncestorType=ListView"
                                                             CommandParameter="Binding RelativeSource=RelativeSource self, Path=Tag"
                                                                        />
        <StackPanel>
    </DataTemplate>
</GridViewColumn.CellTemplate>

我正在尝试获取 Button 的 Tag 属性并将其传递给上面的命令,而不是像这样从列表中删除它。

在 XAML 之上编辑并添加了一个 TextBlock,它使用与 Button 的标记和内容相同的绑定,但不知何故 Button 没有获得值,但 TextBlock 可以!?

    public void DeleteCriterion(object criterionId)
    
        int crtId = (int)criterionId;
        Criterion crt = _criteria.FirstOrDefault((c) => c.CriterionId == crtId);
        if (crt != null)
            _criteria.Remove(crt);
    

但我总是将criteriaId 参数设为空。

我做错了什么?

【问题讨论】:

【参考方案1】:

由于您在按钮内显式设置 DataContext,当您执行 Binding SomeProperty 之类的绑定时,它将假定 SomeProperty 在您刚刚设置的 DataContext 中。尝试使用更明确的绑定,例如:

"Binding RelativeSource=RelativeSource AncestorType=StackPanel, Path=DataContext.CriteriaId" 

这将为您提供正确的 DataContext 的 CriteriaID,就像 TextBlock 一样。

【讨论】:

是的,有效:)。但只是稍微更正"Binding RelativeSource=RelativeSource AncestorType=StackPanel, Path=DataContext.CriteriaId"。谢谢一堆 Jakub。 Jakub,我添加了 StackPanel 来容纳 TextBlock。现在我不需要 TextBlock,我也不需要 StackPanel。在这种情况下,如果我在您建议的答案中设置 Path="GridViewColumn" ,它将不起作用。我是否必须保留 StackPanel 才能完成这项工作? 相信你应该可以绑定DataTemplate 我试过了,CommandParameter="Binding RelativeSource=RelativeSource AncestorType=DataTemplate, Path=DataContext.CriteriaId",但也没有用。 天啊!我没有意识到 DataTemplate 没有 DataContext 属性。试试这个:Binding Path=CriteriaId, RelativeSource=RelativeSource TemplatedParent。如果这不起作用,只需作弊并使用堆栈帧内的按钮。【参考方案2】:

只要你的按钮的Tag 不为空(如果它为空,你就有不同的问题),我看不出你不能像你那样直接绑定到CriterionId 的原因Tag.

【讨论】:

嗨 Jakub,我在上面添加了一个 TextBlock,其绑定与 Button 的 Tag 相同,但 TextBlock 得到更新,而不是 Tag 或按钮的内容! 哦我觉得肯定是和按钮的DataContext有关!

以上是关于使用 WPF + MVVM 中的 Command + CommandParameter 删除列表视图中的行的主要内容,如果未能解决你的问题,请参考以下文章

WPF 事件实现MVVM中的Command绑定

C# WPF MVVM Command Binding

WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参

WPF MVVM DataGrid Button Command绑定

WPF中的Command事件绑定

WPF中的命令(Command)