I have a CustomComboBox component that inherits from ComboBox
with its style copied to another resource dictionary xaml file.
The question is, can I or how do I bind a property from the sub style for ComboBoxToggleButton
used in ComboBoxTemplate
used in CustomComboBoxStyle
?
The property is: GryphlBrush in
<Path x:Name="arrow" Stroke="{Binding GryphlBrush}" ...
The code example below:
<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<!-- ... -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
Border x:Name="templateRoot" SnapsToDevicePixels="true" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" CornerRadius="4">
<Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Transparent">
<Path x:Name="arrow" Stroke="{Binding GryphlBrush}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Fill="{StaticResource ComboBox.Static.Glyph}" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>
</Border>
</Border>
<!-- ... -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ComboBoxTemplate" TargetType="{x:Type ComboBox}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="4">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
<!-- ... -->
<ToggleButton x:Name="toggleButton" BorderBrush="Transparent" BorderThickness="0" Background="Transparent" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxToggleButton}"/>
<!-- ... -->
</Grid>
</Border>
<!-- ... -->
</ControlTemplate>
<Style x:Key="BorderedComboBoxStyles" TargetType="{x:Type components:BorderedComboBox}">
<Setter Property="Template" Value="{StaticResource ComboBoxTemplate}"/>
</Style>
In code behind I only define the dependency property, getters and setters:
public class BorderedComboBox : ComboBox
{
public static readonly DependencyProperty GryphlBrushDP = DependencyProperty.Register(
"GryphlBrush", typeof(Brush), typeof(BorderedComboBox));
private Brush _gryphlBrush;
public Brush GryphlBrush
{
get => _gryphlBrush;
set => _gryphlBrush = value;
}
}
CodePudding user response:
You should adhere to the naming conventions for dependency properties and their getters and setters. Furthermore using nameof
for the property can prevent errors when renaming.
The name of the identifier field that you use to store the name and characteristics of the dependency property must be the Name you chose for the dependency property as part of the Register call, appended by the literal string
Property
. [...]If you fail to follow this naming pattern, designers might not report your property correctly, and certain aspects of property system style application might not behave as expected.
Hence your dependency property definition should look like this:
public class BorderedComboBox : ComboBox
{
public static readonly DependencyProperty GryphlBrushProperty = DependencyProperty.Register(
nameof(GryphlBrush), typeof(Brush), typeof(BorderedComboBox));
private Brush _gryphlBrush;
public Brush GryphlBrush
{
get => _gryphlBrush;
set => _gryphlBrush = value;
}
}
If you want to bind the GryphlBrush
property, in the ToggleButton
control template, you could:
Create a custom toggle button and add a dependency property to it and then bind it to the
GryphlBrush
property on yourBorderedComboBox
.If the toggle button is only used in this context within the combo box, apply a
RelativeSource
binding withAncestorType
, since theBorderedComboBox
is a parent of the toggle button.<Style x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}"> <!--...--> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Border x:Name="templateRoot" SnapsToDevicePixels="true" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" CornerRadius="4"> <Border x:Name="splitBorder" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" SnapsToDevicePixels="true" Margin="0" HorizontalAlignment="Right" BorderThickness="1" BorderBrush="Transparent"> <!--<Path x:Name="arrow" Stroke="{Binding GryphlBrush, RelativeSource={RelativeSource AncestorType={x:Type local:BorderedComboBox}}}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Fill="{StaticResource ComboBox.Static.Glyph}" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/>--> <Path x:Name="arrow" Stroke="{Binding GryphlBrush, RelativeSource={RelativeSource AncestorType={x:Type local:BorderedComboBox}}}" VerticalAlignment="Center" Margin="0" HorizontalAlignment="Center" Data="F1 M 0,0 L 2.667,2.66665 L 5.3334,0 L 5.3334,-1.78168 L 2.6667,0.88501 L0,-1.78168 L0,0 Z"/> </Border> </Border> <!--...--> </ControlTemplate> </Setter.Value> </Setter> </Style>