I have a combobox filled with a list of Objects. I like to highlight an item in a combobox based on a IsHighlighted property of the Object.
I've tried writing my own style but no real success...
<Style x:Key="SimpleComboBoxItem" TargetType="ComboBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border Name="Border" Padding="2" SnapsToDevicePixels="true">
<ContentPresenter x:Name="contentPresenter" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="#FFCCCCCC"/>
</Trigger>
<Trigger Property="Tag" Value="Highlight" SourceName="contentPresenter">
<Setter Property="Background" TargetName="Border" Value="#FFAAF3A0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanx in advance
This should work fine with a simple DataTrigger.
Your Object Class:
public class TestObject
{
public string Name { get; set; }
public bool IsHighlighted { get; set; }
public override string ToString()
{
return this.Name;
}
}
Xaml:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWPF"
Title="MainWindow">
<Grid>
<StackPanel>
<ComboBox>
<ComboBox.Resources>
<Style TargetType="ComboBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsHighlighted}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Resources>
<local:Employee Name="Nick" />
<local:Employee Name="Bob" IsHighlighted="True" />
<local:Employee Name="Fred" />
</ComboBox>
</StackPanel>
</Grid>
</Window>
Note: Unlike the sample above, I'm guessing in your code you're binding the combobox's ItemsSource... which should work just the same. One thing to be careful of though, is if your object's 'IsHighlighted' property can change, you should be implementing INotifyProperty changed to ensure that changing the value will notify the UI that the triggers should refresh.
You might wanna re-define the HighlightBrushKey, overriding default highlight style:
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="FFAAF3A0" />
</ComboBox.Resources>
Should do the trick for you.
(if it is more general, put it directly in the UserControl.Resources / Window.Resources )
Related
I have seen some articles that show how to use AlternationIndex with ListBoxes or ListViews, but I had spent a few hours trying to get alternating background colors on the base ItemsControl class and nothing seems to work. All ListBox samples I saw use ListBoxItem as the target type for the style that sets the background based onAlternationIndex - like this one from MSDN:
<Grid>
<Grid.Resources>
<Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Blue"/>
<Setter Property="Foreground" Value="White"/>
<Style.Triggers>
<Trigger Property="ListBox.AlternationIndex" Value="1">
<Setter Property="Background" Value="CornflowerBlue"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="ListBox.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Navy"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ListBox AlternationCount="3" ItemsSource="{StaticResource data}"
ItemContainerStyle="{StaticResource alternatingWithTriggers}">
</ListBox>
</Grid>
I want to use the ItemsControl because I do not want the selection functionality and I think restyling a ListBox to hide it might not be the best choice.
This is one of the things I was trying:
<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
<Grid>
<!-- some content here -->
</Grid>
</DataTemplate>
<!-- ... -->
<ItemsControl
ItemsSource="{Binding ObservableCollectionItems}"
AlternationCount="2"
>
<ItemsControl.ItemContainerStyle>
<Style>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Grid.Background" Value="Red"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Grid.Background" Value="Blue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
The problem I saw was that the visual tree has a list of ContentPresenters that have ItemsControl.AlternationIndex alternate between 0 and 1, but the Grid in each ContentPresenter has ItemsControl.AlternationIndex set to 0.
There is probably something obvious I am missing...
The ItemContainerStyle is applied to the elements generated by the ItemsControl: ContentPresenter. The ContentPresenter will in turn contain whatever you put in your ItemTemplate. In the case of a ListBox, the ItemContainerStyle is applied to the generated ListBoxItem.
The AlternationCount is, based on what you posted, only available on these generated items. You cannot use the ItemContainerStyle to set the Grid's background, because the Grid is unknown to that Style.
The following would be ideal, but unfortunately ContentPresenter has no background property. It would work for a ListBox (with ListBoxItems) however.
<ItemsControl
ItemsSource="{Binding ObservableCollectionItems}"
AlternationCount="2">
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Blue"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
So you end up writing a style for the grid which binds to the AlternationIndex of your parent ContentPresenter.
<DataTemplate DataType="{x:Type vm:ObservableCollectionItem}">
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContentPresenter}}, Path=(ItemsControl.AlternationIndex)}" Value="1">
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</DataTemplate>
hm... After about 2 hours of playing around, I finally found the solution that simply works:
<ItemsControl ItemsSource="{Binding}" AlternationCount="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent" x:Name="__PART_GRID"></Grid>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter TargetName="__PART_GRID" Property="Background" Value="Red"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter TargetName="__PART_GRID" Property="Background" Value="Blue"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I hope this answer helps others to save some time.
Or, as I found on another post, and it works great for me...
You can simply use a binding...
{Binding
RelativeSource={RelativeSource Mode=TemplatedParent},
Path=(ItemsControl.AlternationIndex)}
NB: remember to add AlterationCount="100" on your ItemsControl
I don't know how any of the prior answers are legit. I couldn't make any of them work (didn't try Jacobi's though). Anyways, I found the path to enlightenment here: http://www.dotnetcurry.com/wpf/1211/wpf-items-control-advanced-topic, which lead me to adding the following in the xaml.cs code-behind:
public sealed class CustomItemsControl : ItemsControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
}
and this in the xaml itself
<local:CustomItemsControl AlternationCount="2"
ItemsSource="{Binding Cells, Mode=OneWay}">
<local:CustomItemsControl.ItemContainerStyle>
<Style TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="WhiteSmoke"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
</local:CustomItemsControl.ItemContainerStyle>
</local:CustomItemsControl>
This was so damn hard to find a working solution to that I'm actually angry
If you don't want to use the DataTemplate approach, you can create a custom control that uses a ContentControl as the item container, therefore allowing you to specify a background color.
Class:
public class ItemsControlAlternating : ItemsControl
{
static ItemsControlAlternating()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating),
new FrameworkPropertyMetadata(typeof(ItemsControlAlternating)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is ContentControl;
}
}
Resource Dictionary:
<Style TargetType="{x:Type c:ItemsControlAlternating}">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Gray"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
Reworked Question to clarify my needs:
I want to add a preview Text to Textboxes when they're empty, just like some of you may know it from Xamarin.
I have found this answer on SO.
This is the Style from the Answer I linked above.
<TextBlock Grid.Row="5"
Grid.Column="1"
VerticalAlignment="Center"
Text="Username:">
</TextBlock>
<TextBox Grid.Row="5"
Grid.Column="3">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Test" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I get the following result:
Since this is working nicely I want to apply it to every TextBox in that Window.
So my approach was to change this line:
<Label Content="Test" Foreground="LightGray" />
I thought maybe changing it to <Label Content="Test" Foreground="LightGray" /> would do the trick, but it is not working.
I guess it's something with the Tag Property and the Type of it (object instead of string).
Since the first approach is working like charm I don't really see why I should need a custom control for that...
So what I tried then is this:
<Window.Resources>
<Style TargetType="TextBox">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
What am I missing - why isn't that working ?
For the reusable textbox, you need to create a custom control. Also for binding doesnot work well with visual brush, so you need some temp object to store the value. Refer my below code.
<Window x:Class="ChkList_Learning.Window4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ChkList_Learning"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Window4" Height="300" Width="300">
<Window.Resources>
<local:Temp x:Key="temp" Value="{Binding ElementName=Hostname, Path=Watermark}"/>
<Style TargetType="{x:Type local:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Resources>
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="{Binding Source={StaticResource temp}, Path=Value}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<local:WatermarkTextBox x:Name="Hostname" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" Watermark="Hello, world.">
</local:WatermarkTextBox>
</Grid>
</Window>
public class Temp : Freezable
{
// Dependency Property
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string),
typeof(Temp), new FrameworkPropertyMetadata(string.Empty));
// .NET Property wrapper
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
protected override System.Windows.Freezable CreateInstanceCore()
{
return new Temp();
}
}
public class WatermarkTextBox : TextBox
{
static WatermarkTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox), new FrameworkPropertyMetadata(typeof(WatermarkTextBox)));
}
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(WatermarkTextBox));
public string Watermark
{
get { return (string)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
}
I need to change my Button background (as SolidColorBrush for example) only when it is not enabled (IsEnabled == false). How can I do?
Have I to modify the Button Style using the XAML or can I do this work programmatically? What is the correct XAML code, to change only the Background when it is not enabled?
I tried the following XAML code but it has no effect:
<Button>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
You can change the background by editing the template. You'll find the default template for Button here.
In the trigger for IsEnabled you can simply add something like this:
<Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}"/>
EDIT:
Try this instead then;
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Overlay" CornerRadius="2">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Overlay" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="Button" IsEnabled="False"/>
</StackPanel>
Just change it to suit your needs.
You can use a Style trigger:
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
<Setter Property="Image.Source" Value="pack://application:,,,/disabled.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
I am attempting to implement HotTracking for a tab control in Wpf. My understanding is this was not included in the wpf tabcontrol and I would like to use it.
For my benefit HotTracking = When mouseover an unselected tab the tab will change color(usually to something between selected and not selected)
I used a bit of my own knowledge and this post How to set MouseOver event/trigger for border in XAML? but I can't seem to make it work.
This is everything.
<Window x:Class="TestingWpF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280">
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
CornerRadius="6,6,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="AliceBlue" />
</Trigger>
<Trigger Property=" Border.IsMouseOver" Value="True">
<Setter Property="Border.Background" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl Grid.ColumnSpan="2" Grid.RowSpan="2" Height="309" HorizontalAlignment="Left" Name="tabControl1" VerticalAlignment="Top" Width="781" Padding="0">
<TabItem Header="tabItem1" >
</TabItem>
<TabItem Header="tabItem2" >
</TabItem>
</TabControl>
</Grid>
</Window>
I figured it out, my problem was this section
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="AliceBlue" />
</Trigger>
<Trigger Property=" Border.IsMouseOver" Value="True">
//Change this line
//<Setter Property="Border.Background" Value="Green" />
//To This
<Setter TargetName="Border" Property="Background" Value="Green" />
</Trigger>
The last Trigger was the one not working. And if you notice I used different properties in the setter. I changesd it to match the other two and it worked
I have DataGrid control from WPF Toolkit in my app. I need replace default TextBlock used for cells with tuned TextBlock. XAML-code looks something like:
<Window.Resources>
<Style x:Key="cellStyle" TargetType="{x:Type tk:DataGridCell}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Background="Yellow" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<tk:DataGrid
ItemsSource="{Binding Path=Products}"
CellStyle="{StaticResource cellStyle}"
AutoGenerateColumns="False">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn
Header="Id"
Binding="{Binding Path=Id}"/>
<tk:DataGridTextColumn
Header="Product"
Binding="{Binding Path=Name}"/>
</tk:DataGrid.Columns>
</tk:DataGrid>
</Grid>
After TextBlock replacement all data binding is lost and all the cells are empty. Adding property Text="{Binding}" to the new TextBlock doesn't help. In this case all the cells contain name of type DataGridTestApp.Product. What will be the right binding expression for TextBlock?
P.S. Just in case: code for MainWindowViewModel
internal sealed class MainWindowViewModel
{
public MainWindowViewModel()
{
_products = new ObservableCollection<Product>()
{
new Product(1, "ProductName1"),
new Product(2, "ProductName2"),
new Product(3, "ProductName3"),
new Product(4, "ProductName4"),
new Product(5, "ProductName5"),
};
}
public ObservableCollection<Product> Products
{
get { return _products; }
}
private ObservableCollection<Product> _products;
}
If you look at the source code to the Toolkit you will find the existing style for the datagrid cell (it uses a content presenter to display the column)
<Style x:Key="{x:Type dg:DataGridCell}" TargetType="{x:Type dg:DataGridCell}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dg:DataGridCell}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static dg:DataGrid.FocusBorderBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
To get your yellow background I would just replace
<Setter Property="Background" Value="Transparent" />
with
<Setter Property="Background" Value="Yellow" />
If you are desperate to override the TextBlock inside then use the above template but add this just inside the Border
<Border.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="0,5" />
<Setter Property="Background" Value="Yellow" />
</Style>
</Border.Resources>
The TextBlock's data context is a Product. If it's the name of the product you want to display, then use this:
<Window.Resources>
<Style x:Key="cellStyle" TargetType="{x:Type tk:DataGridCell}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Background="Yellow" Text="{Binding Name}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Unfortunately, if you override the template, you lose any bindings set up in the DataGridTextColumn.