代码之家  ›  专栏  ›  技术社区  ›  Pete

将DataGrid标头中的按钮绑定到ViewModel

  •  0
  • Pete  · 技术社区  · 6 年前

    我有一个 DataGrid 这与 ICollectionView 我的 ViewModel ,我要为每列筛选它。
    下面是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 我可以将数据上下文传递给我的 视图模型 并搜索此字符串。但是,我更愿意将按钮绑定到 视图模型 ,因此我可以获取此事件起源的列的引用,并在那里适当地处理我的数据。

    我的 视图模型 如下所示:

    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}}}"/>
    

    所有这些都没有触发事件。

    编辑:我可能应该补充一点,更大的目标是创建一个按钮,单击该按钮时,会创建一个动态填充的上下文菜单。我可能完全走错了方向。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Andy    6 年前

    我不理解您对更大目标和动态填充上下文菜单的描述。

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

    但是这是一个完全不同的问题。
    将按钮绑定到datagrid的datacontext中的命令。
    我的数据网格叫做dg(我的内心是一个极简主义者)。
    我的命令有点冗长,它叫ColHeaderCommand。

    这对我很有用:

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

    我的viewmodel是窗口的datacontext,它继承到datagrid。
    您需要某种类型的参数,以便该命令在哪个列中传递,或者您正在使用什么。