通过单击调用 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" />
我想在 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" />