WPF 专栏 header 单击命令绑定命令参数 MVVM

WPF column header click command binding with command parameter MVVM

我正在尝试自己处理 WPF DataGrid 中的排序功能。 我需要能够在单击列 header 时绑定命令,并将绑定的 属性 名称作为命令参数发送给命令。

这是我目前拥有的:

XAML:

       <DataGrid Grid.Row="2" Margin="{StaticResource ControlStartPosition}"
        RowStyle="{StaticResource SelectedRowNoBackgroundColor}"
        CellStyle="{StaticResource SelectedCellNoBackgroundColor}"
        Style="{StaticResource AlternatingRowBackgroundGridStyle}"
        x:Name="MechanicsGrid"  
        ItemsSource="{Binding Mechanics}"
        IsReadOnly="True"
        GridLinesVisibility="All"
        SelectionUnit="FullRow"
        AutoGenerateColumns="False">
        <DataGrid.ColumnHeaderStyle>
            <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MetroDataGridColumnHeader}">
                <Setter Property="Controls:ControlsHelper.ContentCharacterCasing" Value="Normal"/>
                <Setter Property="Command"  Value="{Binding DataContext.GridSortCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                <Setter Property="CommandParameter" Value="{Binding Path=Content, RelativeSource={RelativeSource Self}}"/>
            </Style>

        </DataGrid.ColumnHeaderStyle>
        <DataGrid.Columns>
                <DataGridTextColumn  Width="*"  Header="{x:Static p:MechanicsView.GridMechanicNameColumn}" Binding="{Binding Name}" />

                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Command="{Binding Path=DataContext.DeleteMechanicCommand,RelativeSource= {RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}" 
                                CommandParameter="{Binding Path=Id}" Width="27" Height="27" Margin="10 -5 10 -5" Style="{DynamicResource MetroCircleButtonStyle}">
                                <Rectangle Width="11" Height="11" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}">
                                    <Rectangle.OpacityMask>
                                        <VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_close}" />
                                    </Rectangle.OpacityMask>
                                </Rectangle>
                            </Button>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

视图模型:

    private ObservableCollection<MechanicModel> mechanics;
    public ObservableCollection<MechanicModel> Mechanics
    {
        get
        {
            return mechanics;
        }
        set
        {
            Set(() => Mechanics, ref mechanics, value);
        }
    }

网格绑定到此 属性,在机械模型中我只有两个属性:

    private int id;
    public int Id
    {
        get
        {
            return id;
        }
        set
        {
            Set(() => Id, ref id, value);
        }
    }

    private string name;
    public string Name
    {
        get
        {
            return  name;
        }
        set
        {
            Set(() => Name, ref  name, value);
            ValidateProperty(nameof(Name), value);
        }
    }

命令:

绑定到列header的命令是:

    private RelayCommand<object> gridSortCommand;
    public RelayCommand<object> GridSortCommand
    {
        get
        {
            return gridSortCommand
                ?? (gridSortCommand = new RelayCommand<object>(
                p =>
                {

                },
                p => true));
        }
    }

所以对于 p => 我目前得到列的标题,我想得到的是 属性 名称,在这种情况下至少 "Name" 作为字符串,这样我就可以构建我的排序视图中的逻辑 model.Unfortenatly 我无法将其绑定为命令参数。

如果你想在你的命令中传递参数,你需要做的就是使用MultiBinding
然后可以按如下方式使用:

<MultiBinding>
    <Binding Path="Id"/>
    <Binding Path="Name"/>
    <Binding Path="DirectionOfSort"/>
</MultiBinding>  

但是,要做到这一点,您需要稍微改变一下 xaml。
所以来自:

<Setter Property="CommandParameter" Value="{Binding Path=Content, RelativeSource={RelativeSource Self}}"/>  

您需要将其更改为:

<DataGrid>
    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="CommandParameter">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource multi}">
                        <Binding Path="Id"/>
                        <Binding Path="Name"/>
                        <Binding Path="{x:Static util:Enumeration.EDirection}"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.ColumnHeaderStyle>
</DataGrid>  

你的转换器是这样的:

namespace View.Converters
{
    public class MultiValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.Clone();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}  

并且在 xaml 中:

<converter:MultiValueConverter x:Key="multi"/>

你这样引用的:

xmlns:converter="clr-namespace:View.Converters"

你的 Util 基本上是一个在你的 xaml 中引用的枚举,如下所示:

xmlns:util="clr-namespace:Utilities;assembly=Utilities"