DataGrid wpf MVVM 内的按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20858692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:21:22  来源:igfitidea点击:

Button inside DataGrid wpf MVVM

c#wpfeventsmvvmdatagrid

提问by Bhramar

I am following MVVM in this project.

我在这个项目中关注 MVVM。

I have WPF datagrid,

我有 WPF 数据网格,

ItemsSource (ItemsSource="{Binding Documents}")binded to an ObservableCollection<Document>,

ItemsSource(ItemsSource="{Binding Documents}")绑定到ObservableCollection<Document>,

SelectedItem (SelectedItem="{Binding CurrentDocument, Mode=TwoWay}")binded to WorkQueueDocument,

SelectedItem(SelectedItem="{Binding CurrentDocument, Mode=TwoWay}")绑定到WorkQueueDocument,

I also have used Interaction Triggers to capture the Double click of the mouse - in order to load the selected Document in a New WIndow.

我还使用交互触发器来捕获鼠标的双击 - 以便在新窗口中加载选定的文档。

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDoubleClick">
        <i:InvokeCommandAction Command="{Binding ShowViewerCommand}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

I Have defined/binded the columns of my datagrid to corresponding attibutes of WorkQueueDocument class.

我已将数据网格的列定义/绑定到 WorkQueueDocument 类的相应属性。

<DataGrid.Columns>
    <DataGridTextColumn Width="Auto"
                            MinWidth="100"
                            Header="Name"                                                            
                            Binding="{Binding Name}">
        <DataGridTextColumn.ElementStyle>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="2,0,0,0" />
                <Setter Property="ToolTip" Value="{Binding Name}" />
            </Style>
        </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>

    <!-- Many Other Columns Here... -->
</DataGrid.Columns>

<DataGrid.ColumnHeaderStyle>
        <!-- I have various designer style's properties defined here -->
</DataGrid.ColumnHeaderStyle>


I am supposed to load the document when the user selects the row (document) in the grid - for that CurrentDocument property is defined as follows:

我应该在用户选择网格中的行(文档)时加载文档 - 对于该 CurrentDocument 属性定义如下:

public WorkQueueDocument CurrentDocument
{
    get
    {
        return this.currentDocument;
    }
    set
    {

        if (this.currentDocument != value)
        {
            this.currentDocument = value;
            this.OnPropertyChanged("CurrentDocument");
            this.IsDocumentSelected = true;

    // If we are in progress already, don't do anything
            if (!IsLoading && this.currentDocument != null)
            {
                IsLoading = true;
                LoadDocumentBackgroundWorker();// loading documenting async
            }


            if (this.currentDocument == null)
            {
                this.IsDocumentSelected = false;
            }
        }

    }
}

Now, the problem is - I want to add a Delete Button column to this datagrid, such that when user presses Delete button - the document gets deleted directly without loading the document. I added following xaml to <DataGrid.Columns>

现在,问题是 - 我想向这个数据网格添加一个删除按钮列,这样当用户按下删除按钮时 - 文档被直接删除而不加载文档。我将以下 xaml 添加到<DataGrid.Columns>

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
    <Button Name="DeleteBatch" 
            Content="Delete"
            Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.DeleteCommand}"
            CommandParameter="Delete"/>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

This DeleteCommandain't getting fired. I tried to figure out WHY and discovered that I have

DeleteCommand不会被解雇。我试图找出原因并发现我有

1st command is in datagrid for loading document on selection of row

第一个命令在数据网格中,用于在选择行时加载文档

ItemsSource="{Binding Documents}"

2nd command is on delete button which is in coluumn of above datagrid

第二个命令位于删除按钮上,该按钮位于上述数据网格的列中

<Button Name="Delete" 
Content="Delete" 
Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.DeleteCommand}" 
CommandParameter="Delete">

, I am able to access only one command at a time. When i click the button - the row ('obviously') gets selected and executed associated binding for 'SelectedItem' but does not follow up calling the

,我一次只能访问一个命令。当我单击按钮时 - 行(“显然”)被选中并执行“ SelectedItem”的关联绑定,但没有跟进调用

DeleteCommand( which ideally should ) . But if I remove this 'SelectedItem' property - the deleteCommand gets triggered ( but then i dont get the selected row).

DeleteCommand(理想情况下应该)。但是如果我删除这个“ SelectedItem”属性 - deleteCommand 被触发(但我没有得到选定的行)。

Also (while debugging i noticed) the **DeleteCommandgets executed on when we press(click) second time (coz now the row is already selected)**

另外(在调试时我注意到)当我们第二次按下(单击)时**DeleteCommand被执行(因为现在该行已经被选中)**

I googled - and found few probablesolutions, like Priority Binding and Tunneling , but unable to implement. Please guide me through this.

我用谷歌搜索 - 并发现了一些可能的解决方案,例如 Priority Binding 和 Tunneling ,但无法实施。请指导我完成此操作。

I got this link, but not sure if this is the only way.

我得到了这个链接,但不确定这是否是唯一的方法。

P.S : 1. I am using WPF , .Net 4.0 and MVVM

PS:1. 我使用 WPF、.Net 4.0 和 MVVM

  1. Please do not suggest Third Party solutions. [unless the only option]
  1. 请不要建议第三方解决方案。【除非唯一的选择】

回答by FPGA

  • The delete command parameter should just be

    CommandParameter="{Binding}"

  • this means that the command parameter is the document reference itself thus you can do the following in your command

    yourDocumentObservableCollection.Remove(CommandParameter)

  • 删除命令参数应该只是

    CommandParameter="{Binding}"

  • 这意味着命令参数是文档引用本身,因此您可以在命令中执行以下操作

    yourDocumentObservableCollection.Remove(CommandParameter)

This way you wont need to care about if the Document is focused or not.

这样你就不需要关心文档是否有焦点。