- SelectionUnit = Cell is needed to don't mess things up when the mouse button is pressed on the Highlight button and depressed outside.
- Focusable = False is needed to forbid tabbing into the text cells.
- IsHitTestVisible = False is needed to forbid selecting a text cell with the mouse.
- Background = Null is needed to forbid selecting the button cell when the empty space around the button is clicked.
- IsHitTestVisible = True is needed for the button to be clickable, because if the cell isn't clickable, the button won't be either.
- MultiBinding is needed because in the existing codebase the highlighting wasn't handled with a property on the Employee class.
MainWindow.xaml:
<Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:this="clr-namespace:WpfApplication3" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid x:Name="EmployeeGrid" ItemsSource="{Binding Employees}" AutoGenerateColumns="False" IsReadOnly="True" SelectionUnit="Cell"> <DataGrid.Resources> <this:EqualityConverter x:Key="EqualityConverter"/> <Style TargetType="DataGridCell"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="DataGridCell"> <Border Background="{TemplateBinding Background}"> <ContentPresenter/> </Border> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="Focusable" Value="False"/> <Setter Property="IsHitTestVisible" Value="False"/> <Setter Property="Background" Value="{x:Null}"/> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource EqualityConverter}"> <Binding/> <Binding ElementName="EmployeeGrid" Path="DataContext.HighlightedEmployee"/> </MultiBinding> </DataTrigger.Binding> <Setter Property="Background" Value="LightBlue"/> <Setter Property="Foreground" Value="White"/> </DataTrigger> </Style.Triggers> </Style> <Style x:Key="ClickableCell" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> <Setter Property="IsHitTestVisible" Value="True"/> </Style> </DataGrid.Resources> <DataGrid.Columns> <DataGridTextColumn Header="Name" Binding="{Binding Name}"/> <DataGridTextColumn Header="Age" Binding="{Binding Age}"/> <DataGridTemplateColumn CellStyle="{StaticResource ClickableCell}"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="Highlight" Margin="10" Click="HighlightClick"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
MainWindow.xaml.cs:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace WpfApplication3 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var employees = new List<Employee> { new Employee { Name = "aa", Age = 10 }, new Employee { Name = "bb", Age = 20 } }; DataContext = new Company { Employees = employees, HighlightedEmployee = employees[1] }; } void HighlightClick(object sender, RoutedEventArgs e) { var company = DataContext as Company; var button = e.OriginalSource as Button; company.HighlightedEmployee = button.DataContext as Employee; } } public class Company : INotifyPropertyChanged { Employee _highlightedEmployee; public List<Employee> Employees { get; set; } public event PropertyChangedEventHandler PropertyChanged; public Employee HighlightedEmployee { get { return _highlightedEmployee; } set { _highlightedEmployee = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("HighlightedEmployee")); } } } } public class Employee { public string Name { get; set; } public int Age { get; set; } } public class EqualityConverter : IMultiValueConverter { public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture) { return values[0] == values[1]; } public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }