My intention is to define a dependency property Position
for list-elements to style them different if they are on the edge.
I have a dependency property (along with its default get and set methods that are not shown):
public static readonly DependencyProperty PositionProperty =
DependencyProperty.RegisterAttached(
"Position",
typeof(Position),
typeof(ClientView),
new FrameworkPropertyMetadata(
Position.Normal));
a TabControl:
<TabControl x:Name="Items" ItemContainerStyle="{DynamicResource TabItem}"/>
and a template for those TabItems:
<Style x:Key="TabItem" TargetType="{x:Type TabItem}">
... <Setter Property="Template"> <Setter.Value>
<Grid SnapsToDevicePixels="true">
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="Bd">
<StackPanel Orientation="Horizontal">
<TextBlock
Text="{Binding Position, RelativeSource={RelativeSource
AncestorType={x:Type client:ClientView}}}"/>
<ContentPresenter x:Name="Content" ContentSource="Header"/>
</StackPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="client:ClientView.Position" Value="Last">
<Setter Property="CornerRadius" TargetName="Bd" Value="0,0,0,4"/>
</Trigger>
...
On the codebehind of my ClientView
class, i fill those properties when the items generator tells me that he created those tabitems:
var gen = Items.ItemContainerGenerator;
gen.StatusChanged += (sender, args) =>
{
if (gen.Status == GeneratorStatus.ContainersGenerated)
{
var cnt = Items.Items.Count;
if (cnt > 0)
{
if (cnt == 1)
{
gen.ContainerFromItem(Items.Items[0])
.SetValue(PositionProperty, Position.Normal);
}
else
{
gen.ContainerFromItem(Items.Items[0])
.SetValue(PositionProperty, Position.First);
if (cnt > 2)
{
for (int i = 1; i < cnt - 2; i++)
{
gen.ContainerFromItem(Items.Items[i])
.SetValue(PositionProperty, Position.Normal);
}
}
gen.ContainerFromItem(Items.Items[cnt - 1])
.SetValue(PositionProperty, Position.Last);
}
}
}
};
When i run this code, i can debug those event and see the correct values are set, but they never appear in the view. The text of the textbox always shows "Normal" which is the default value. What am i doing wrong here?
What if you bind bind the TextBlock.Text
property like this
<TextBlock Text="{Binding
Path=(ClientView.Position),
RelativeSource={RelativeSource Mode=TemplatedParent}}" />
since the attached property is set on the styled TabItem, i.e. the TemplatedParent
.
EDIT: What if you also set the Border.CornerRadius
property by a binding with a binding converter that converts from Position to an appropriate CorderRadius value:
<Border CornerRadius="{Binding
Path=(ClientView.Position),
RelativeSource={RelativeSource Mode=TemplatedParent},
Converter={StaticResource PositionToCornerRadiusConverter}}" />