将DataGrid标头中的Button绑定到ViewModel

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将DataGrid标头中的Button绑定到ViewModel相关的知识,希望对你有一定的参考价值。

我有一个DataGrid绑定到我的ICollectionView中的ViewModel“Employees”,我想过滤每列。 这是XAML的样子:

<DataGrid ItemsSource="{Binding Employees}"
attachedBehaviors:DataGridColumnsBehavior.BindableColumns="{Binding EmployeeColumns}">
            <DataGrid.ColumnHeaderStyle>
                <Style TargetType="DataGridColumnHeader">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="16"/>
                                    </Grid.ColumnDefinitions>
                                    <TextBlock Text="{Binding}" Grid.Column="0"/>
                                    <Button Content="v" Grid.Column="1" Click="ButtonClick"/>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DataGrid.ColumnHeaderStyle>
        </DataGrid>

这工作正常,当调用ButtonClick时,我可以将数据上下文传递给我的ViewModel并搜索此字符串。但是,我更喜欢将按钮绑定到我的ViewModel中的事件,因此我可以获得对此事件源自的列的引用,并在那里适当地处理我的数据。

我的ViewModel看起来像这样:

class ViewModel : ChangeNotifier
{
    public ICollectionView Employees { get; private set; }

    public ViewModel()
    {
        var _employees = new List<Employee>{...
        Employees = CollectionViewSource.GetDefaultView(_employees);
        EmployeeColumns = new ObservableCollection<DataGridColumn>();
        EmployeeColumns.Add(new DataGridTextColumn { Header = "First Name", Binding = new Binding("FirstName") });
        EmployeeColumns.Add(new DataGridTextColumn { Header = "Last Name", Binding = new Binding("LastName") });

        FilterMenu = new RelayCommand(new Action<object>(FilterContextMenu));
    }
    private ICommand filtermenu;
    public ICommand FilterMenu
    {
        get
        {
            return filtermenu;
        }
        set
        {
            filtermenu = value;
        }
    }
    public static void FilterContextMenu(object obj)
    {
        MessageBox.Show("Event Fired!");
    }

    public ObservableCollection<DataGridColumn> EmployeeColumns { get; private set; }
}

所以我的问题是:我如何绑定到FilterContextMenu事件?

我试过了:

<Button Content="v" Grid.Column="1" Command="{Binding FilterMenu}"/>

并且:

<Button Content="v" Grid.Column="1" Command="{Binding FilterMenu, RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>

这些都没有触发事件。

编辑:我可能应该补充一点,更大的目标是创建一个按钮,单击该按钮可创建动态填充的上下文菜单。我可能在这里完全错误的轨道。

答案

我没有按照您对更大目标和动态填充的上下文菜单的描述。

听起来它会有一些更具挑战性的问题来获取对窗口中任何datacontext的引用。 contextmenu通常依赖于放置目标来获取任何上下文,因为它不是窗口的一部分。 如果你打算从那里传递命令那么这可能会变得非常复杂。

但是......这完全是一个不同的问题。 将按钮绑定到datagrid的datacontext中的命令。 我的数据网格叫做dg(我心里很简约)。 我的命令有点罗嗦,它叫做ColHeaderCommand。

这对我有用:

<DataGridTextColumn.Header>
    <Button Content="Title" Command="{Binding DataContext.ColHeaderCommand, ElementName=dg}"/>
</DataGridTextColumn.Header>

我的viewmodel是窗口的datacontext,它继承到datagrid。 您将需要某种参数来传递该命令以传入哪个列或您正在做的任何事情。

以上是关于将DataGrid标头中的Button绑定到ViewModel的主要内容,如果未能解决你的问题,请参考以下文章

在DataGrid中绑定自定义标头控件

WPF MVVM DataGrid Button Command绑定

如何将 DataGrid 中的文本框绑定到 Wpf 中的列表?

将 DataGrid 行中的 DoubleClick 命令绑定到 VM

如何使用 MVVM 将数据绑定到 DataGrid 中的 DataGridComboBoxColumn

DataGrid中的WPF绑定到DataContext