简体   繁体   中英

Binding Button in DataGrid header to ViewModel

I have a DataGrid that is bound to an ICollectionView "Employees" in my ViewModel , which I want to filter for each column.
Here's what the XAML looks like:

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

This works fine and when calling ButtonClick I could pass the data context along to my ViewModel and search for this string. However, what I would prefer is to bind the button to an event in my ViewModel , so I can get a reference to the column from which this event originated and appropriately handle my data there.

My ViewModel looks like this:

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; }
}

So my question is: How do I bind to the FilterContextMenu event?

I've tried:

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

And also:

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

None of which triggered the event.

Edit: I probably should add that the greater goal is to create a button that, when clicked, creates a dynamically populated context menu. I may be on the completely wrong track here.

I don't follow your description of the greater goal and dynamically populated context menu.

That sounds like it will have it's own set of somewhat more challenging problems getting a reference to any datacontext in the window. A contextmenu usually relies on placement target to get anything contextual because it isn't part of the window.
If you intend passing commands through from that then this could well get quite complicated.

But... that's a different question entirely.
Binding a button to the command which is in the datacontext of the datagrid.
My datagrid is called dg ( I'm a minimalist at heart ).
I got a bit wordy with my command and it's called ColHeaderCommand.

This works for me:

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

My viewmodel is the datacontext of the window, which is inherited down to the datagrid.
You will want some sort of a parameter for that command to pass in what column or whatever you're doing whatever with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM