WPF列标题单击命令绑定命令参数MVVM

时间:2016-04-27 10:03:25

标签: wpf xaml sorting datagrid command

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

以下是我目前的情况:

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>

的ViewModels:

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

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

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

命令:

绑定到列标题的命令是:

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

                },
                p => true));
        }
    }

因此对于p =&gt;我目前得到列的标题,我想得到的是属性名称,在这种情况下至少“Name”作为字符串,所以我可以在视图模型中构建我的排序逻辑。不幸的是我不能将它绑定为命令参数。

1 个答案:

答案 0 :(得分:1)

如果您想在命令中传递参数,您只需使用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"