I would like to create a hyperlink-column in wpf but rather with a command-binding instead of an 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>
This works great but I have to select the row first before I can click the link. It would be achievable with a datatrigger which sets the row to selected on hover, but I don't really want do select the row on hover.
Any better ideas?
I came up with this solution. First of all create a new DataGridCommandColumn inherited by 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);
}
}
}
Then create a proxy:
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));
}
Later you can use it:
<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" />