通过单击调用 DataGrid 列上的命令

Invoke command on a DataGridcolumn with single-click

我想在 wpf 中创建一个 hyperlink 列,但使用命令绑定而不是 uri。

 <DataGridTemplateColumn Header="{lex:Loc newmaterialnumber}" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock TextDecorations="Underline" Text="{Binding NewMaterialnumber}"  Cursor="Hand" VerticalAlignment="Center" HorizontalAlignment="Left">
                            <TextBlock.InputBindings>
                                <MouseBinding MouseAction="LeftClick" Command="{Binding DataContext.OpenNewMaterialnumberCommand, RelativeSource={RelativeSource AncestorType={x:Type local:ArticleInfoSearchWindow}}}" />
                            </TextBlock.InputBindings>
                        </TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

效果很好,但我必须先 select 该行才能单击 link。这可以通过将行设置为悬停时 selected 的数据触发器来实现,但我真的不想 select 悬停时行。

有更好的主意吗?

我想到了这个解决方案。首先创建一个新的DataGridCommandColumn 继承自DataGridBoundColumn.

public class DataGridCommandColumn : DataGridBoundColumn
{
    [Bindable(true)]
    public ICommand Command
    {
        get => (ICommand)GetValue(CommandProperty);
        set => SetValue(CommandProperty, value);
    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
        nameof(Command),
        typeof(ICommand),
        typeof(DataGridCommandColumn));

    [Bindable(true)]
    public int FontSize
    {
        get => (int)GetValue(FontSizeProperty);
        set => SetValue(FontSizeProperty, value);
    }

    public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
        nameof(FontSize),
        typeof(int),
        typeof(DataGridCommandColumn));


    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        throw new NotImplementedException();
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var button = new Button();

        button.SetResourceReference(FrameworkElement.StyleProperty, "ToolButonWithDisabledRecognizesAccessKey");
        button.SetResourceReference(Control.ForegroundProperty, "PrimaryHueMidBrush");

        button.Height = 20;
        button.VerticalContentAlignment = VerticalAlignment.Top;
        button.HorizontalContentAlignment = HorizontalAlignment.Left;
        button.HorizontalAlignment = HorizontalAlignment.Left;
        button.Padding = new Thickness(0);
        button.FontWeight = FontWeights.Normal;
        if (FontSize != 0)
        {
            button.FontSize = FontSize;
        }


        button.Click += Button_Click;
        BindingOperations.SetBinding(button, ContentControl.ContentProperty, Binding);

        return button;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (Command == null)
        {
            return;
        }

        if (Command.CanExecute(null))
        {
            Command.Execute(null);
        }
    }
}

然后创建代理:

public class ViewModelProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new ViewModelProxy();
    }

    public ViewModelBase ViewModel
    {
        get => (ViewModelBase)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, value);
    }

    public static readonly DependencyProperty ViewModelProperty = 
        DependencyProperty.Register("ViewModel", typeof(ViewModelBase), typeof(ViewModelProxy), new UIPropertyMetadata(null));
}

以后可以使用:

<utility:ViewModelProxy  x:Key="ViewModelProxy" ViewModel="{Binding}" />

<controls:DataGridCommandColumn Header="{lex:Loc submissionnumber}" Binding="{Binding SubmissionNumber}"  Command="{Binding ViewModel.OpenReceivableSubmissionNumberCommand,  Source={StaticResource ViewModelProxy}}" Width="Auto"  />