How to use BasedOn to template a toggle button in Generic.xaml?
wpf C# xaml
In my Generic.xaml, I have many styles of the form:
<Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The only difference between all these toggle buttons is the Path definition and the Fill color.
Could this style be templated/simplified in such a way where only the Path and Fill color need be supplied?
That is something along the lines of :
<Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
<Setter Property = "Path" Value="InsideQuarter3"/>
<Setter Property = "Fill" Value="DarkOrange"/>
</Style>
Thank you for any help.
Edit#1
Well, I thought I had it--I was wrong. The below code will correctly set the Path Data and Fill properties. However, only the first created ToggleButton keeps the "MouseOver" and other ControlTemplate.Triggers. I need ALL the toggle buttons in the RingControl to respect their own triggers.
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
public static Geometry GetData(DependencyObject obj)
{
return (Geometry)obj.GetValue(DataProperty);
}
public static void SetData(DependencyObject obj, Geometry value)
{
obj.SetValue(DataProperty, value);
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));
public static Brush GetFill(DependencyObject obj)
{
return (Brush)obj.GetValue(FillProperty);
}
public static void SetFill(DependencyObject obj, Brush value)
{
obj.SetValue(FillProperty, value);
}
// Using a DependencyProperty as the backing store for Fill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FillProperty =
DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));
}
Generic.xaml -- BaseButtonStyle
<Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
<Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}"
Stroke="Black"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Generic.xaml -- ModifiedButtonStyle1
<Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
</Style>
<Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
</Style>
<Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
</Style>
Generic.xaml -- Using the ModifiedButtonStyles in a custom control, RingControl
<Style TargetType="{x:Type local:RingButtons2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RingButtons2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox>
<Grid>
<!--Outer Rim -->
<Path Data="{StaticResource OuterRim}" Fill="Silver" Stroke="Black" />
<Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />
<ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
<ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
<ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
........................................................
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using the RingControl2 in the user interface:
<w:RingButtons2/>
It would appear that clicking anywhere in the RingButtons2 control results only in the first defined togglebutton responding -- not any of the others.
How can I fix this so that each of the togglebuttons acts independently of the others and respects its own controltemplate triggers?
Thanks again.
Edit#2
Upon removing the TextBlock definition from the BaseButtonStyle,
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
ALL WORKS! Why is this??
Thanks.
wpf generic.xaml
add a comment |
wpf C# xaml
In my Generic.xaml, I have many styles of the form:
<Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The only difference between all these toggle buttons is the Path definition and the Fill color.
Could this style be templated/simplified in such a way where only the Path and Fill color need be supplied?
That is something along the lines of :
<Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
<Setter Property = "Path" Value="InsideQuarter3"/>
<Setter Property = "Fill" Value="DarkOrange"/>
</Style>
Thank you for any help.
Edit#1
Well, I thought I had it--I was wrong. The below code will correctly set the Path Data and Fill properties. However, only the first created ToggleButton keeps the "MouseOver" and other ControlTemplate.Triggers. I need ALL the toggle buttons in the RingControl to respect their own triggers.
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
public static Geometry GetData(DependencyObject obj)
{
return (Geometry)obj.GetValue(DataProperty);
}
public static void SetData(DependencyObject obj, Geometry value)
{
obj.SetValue(DataProperty, value);
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));
public static Brush GetFill(DependencyObject obj)
{
return (Brush)obj.GetValue(FillProperty);
}
public static void SetFill(DependencyObject obj, Brush value)
{
obj.SetValue(FillProperty, value);
}
// Using a DependencyProperty as the backing store for Fill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FillProperty =
DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));
}
Generic.xaml -- BaseButtonStyle
<Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
<Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}"
Stroke="Black"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Generic.xaml -- ModifiedButtonStyle1
<Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
</Style>
<Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
</Style>
<Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
</Style>
Generic.xaml -- Using the ModifiedButtonStyles in a custom control, RingControl
<Style TargetType="{x:Type local:RingButtons2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RingButtons2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox>
<Grid>
<!--Outer Rim -->
<Path Data="{StaticResource OuterRim}" Fill="Silver" Stroke="Black" />
<Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />
<ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
<ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
<ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
........................................................
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using the RingControl2 in the user interface:
<w:RingButtons2/>
It would appear that clicking anywhere in the RingButtons2 control results only in the first defined togglebutton responding -- not any of the others.
How can I fix this so that each of the togglebuttons acts independently of the others and respects its own controltemplate triggers?
Thanks again.
Edit#2
Upon removing the TextBlock definition from the BaseButtonStyle,
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
ALL WORKS! Why is this??
Thanks.
wpf generic.xaml
add a comment |
wpf C# xaml
In my Generic.xaml, I have many styles of the form:
<Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The only difference between all these toggle buttons is the Path definition and the Fill color.
Could this style be templated/simplified in such a way where only the Path and Fill color need be supplied?
That is something along the lines of :
<Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
<Setter Property = "Path" Value="InsideQuarter3"/>
<Setter Property = "Fill" Value="DarkOrange"/>
</Style>
Thank you for any help.
Edit#1
Well, I thought I had it--I was wrong. The below code will correctly set the Path Data and Fill properties. However, only the first created ToggleButton keeps the "MouseOver" and other ControlTemplate.Triggers. I need ALL the toggle buttons in the RingControl to respect their own triggers.
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
public static Geometry GetData(DependencyObject obj)
{
return (Geometry)obj.GetValue(DataProperty);
}
public static void SetData(DependencyObject obj, Geometry value)
{
obj.SetValue(DataProperty, value);
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));
public static Brush GetFill(DependencyObject obj)
{
return (Brush)obj.GetValue(FillProperty);
}
public static void SetFill(DependencyObject obj, Brush value)
{
obj.SetValue(FillProperty, value);
}
// Using a DependencyProperty as the backing store for Fill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FillProperty =
DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));
}
Generic.xaml -- BaseButtonStyle
<Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
<Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}"
Stroke="Black"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Generic.xaml -- ModifiedButtonStyle1
<Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
</Style>
<Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
</Style>
<Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
</Style>
Generic.xaml -- Using the ModifiedButtonStyles in a custom control, RingControl
<Style TargetType="{x:Type local:RingButtons2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RingButtons2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox>
<Grid>
<!--Outer Rim -->
<Path Data="{StaticResource OuterRim}" Fill="Silver" Stroke="Black" />
<Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />
<ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
<ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
<ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
........................................................
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using the RingControl2 in the user interface:
<w:RingButtons2/>
It would appear that clicking anywhere in the RingButtons2 control results only in the first defined togglebutton responding -- not any of the others.
How can I fix this so that each of the togglebuttons acts independently of the others and respects its own controltemplate triggers?
Thanks again.
Edit#2
Upon removing the TextBlock definition from the BaseButtonStyle,
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
ALL WORKS! Why is this??
Thanks.
wpf generic.xaml
wpf C# xaml
In my Generic.xaml, I have many styles of the form:
<Style x:Key="ToggleButtonStyle12" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Path x:Name="path1" Data="{StaticResource InsideQuarter3}" Fill="DarkOrange" Stroke="Black" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The only difference between all these toggle buttons is the Path definition and the Fill color.
Could this style be templated/simplified in such a way where only the Path and Fill color need be supplied?
That is something along the lines of :
<Style x:Key="ToggleButtonStyle12" BasedOn(??????)>
<Setter Property = "Path" Value="InsideQuarter3"/>
<Setter Property = "Fill" Value="DarkOrange"/>
</Style>
Thank you for any help.
Edit#1
Well, I thought I had it--I was wrong. The below code will correctly set the Path Data and Fill properties. However, only the first created ToggleButton keeps the "MouseOver" and other ControlTemplate.Triggers. I need ALL the toggle buttons in the RingControl to respect their own triggers.
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
public static Geometry GetData(DependencyObject obj)
{
return (Geometry)obj.GetValue(DataProperty);
}
public static void SetData(DependencyObject obj, Geometry value)
{
obj.SetValue(DataProperty, value);
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.RegisterAttached("Data", typeof(Geometry), typeof(ButtonProperties), new PropertyMetadata(null));
public static Brush GetFill(DependencyObject obj)
{
return (Brush)obj.GetValue(FillProperty);
}
public static void SetFill(DependencyObject obj, Brush value)
{
obj.SetValue(FillProperty, value);
}
// Using a DependencyProperty as the backing store for Fill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FillProperty =
DependencyProperty.RegisterAttached("Fill", typeof(Brush), typeof(ButtonProperties), new PropertyMetadata(null));
}
Generic.xaml -- BaseButtonStyle
<Style x:Key="BaseButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
<Path x:Name="path1" Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Data)}"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.Fill)}"
Stroke="Black"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="path1" Property = "Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Blink_On}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Blink_Off}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Generic.xaml -- ModifiedButtonStyle1
<Style x:Key="ModifiedButtonStyle1" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc0}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightGreen"/>
</Style>
<Style x:Key="ModifiedButtonStyle2" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc45}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightPink"/>
</Style>
<Style x:Key="ModifiedButtonStyle3" TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="local:ButtonProperties.MyForegroundColor" Value="Red" />
<Setter Property="local:ButtonProperties.Data" Value="{StaticResource Arc90}" />
<Setter Property="local:ButtonProperties.Fill" Value="LightCoral"/>
</Style>
Generic.xaml -- Using the ModifiedButtonStyles in a custom control, RingControl
<Style TargetType="{x:Type local:RingButtons2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RingButtons2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox>
<Grid>
<!--Outer Rim -->
<Path Data="{StaticResource OuterRim}" Fill="Silver" Stroke="Black" />
<Path Data="{StaticResource OuterWheelBackground}" Fill="White" Stroke="Black" />
<ToggleButton x:Name="PART_Button1" Style="{StaticResource ModifiedButtonStyle1}"/>
<ToggleButton x:Name="PART_Button2" Style="{StaticResource ModifiedButtonStyle2}"/>
<ToggleButton x:Name="PART_Button3" Style="{StaticResource ModifiedButtonStyle3}"/>
........................................................
</Grid>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using the RingControl2 in the user interface:
<w:RingButtons2/>
It would appear that clicking anywhere in the RingButtons2 control results only in the first defined togglebutton responding -- not any of the others.
How can I fix this so that each of the togglebuttons acts independently of the others and respects its own controltemplate triggers?
Thanks again.
Edit#2
Upon removing the TextBlock definition from the BaseButtonStyle,
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
ALL WORKS! Why is this??
Thanks.
wpf generic.xaml
wpf generic.xaml
edited Dec 31 '18 at 4:19
Alan Wayne
asked Dec 30 '18 at 5:16
Alan WayneAlan Wayne
1,63122251
1,63122251
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
If the target control has dependency properties that you can use for those custom bindings then you can use TemplateBinding, here's an example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
Which you would then refer to like so:
<Grid>
<Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>
However, in the example you've given above you're using a Path and a Fill inside a template, which I'm guessing don't have associated properties. In this case your options are to either create a new control and add those properties to it or, preferably, use attached properties. In the case of the latter you'd create an attached property like this:
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}
And then you'd reference and override it like this in your XAML:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>
These are more-or-less the same, it's just that in the first case you're using existing properties already inside the control (or creating a new control that has them) whereas in the second case you're declaring and attaching them to an existing control externally.
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something likeGrid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.
– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53975433%2fhow-to-use-basedon-to-template-a-toggle-button-in-generic-xaml%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If the target control has dependency properties that you can use for those custom bindings then you can use TemplateBinding, here's an example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
Which you would then refer to like so:
<Grid>
<Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>
However, in the example you've given above you're using a Path and a Fill inside a template, which I'm guessing don't have associated properties. In this case your options are to either create a new control and add those properties to it or, preferably, use attached properties. In the case of the latter you'd create an attached property like this:
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}
And then you'd reference and override it like this in your XAML:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>
These are more-or-less the same, it's just that in the first case you're using existing properties already inside the control (or creating a new control that has them) whereas in the second case you're declaring and attaching them to an existing control externally.
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something likeGrid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.
– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
|
show 2 more comments
If the target control has dependency properties that you can use for those custom bindings then you can use TemplateBinding, here's an example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
Which you would then refer to like so:
<Grid>
<Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>
However, in the example you've given above you're using a Path and a Fill inside a template, which I'm guessing don't have associated properties. In this case your options are to either create a new control and add those properties to it or, preferably, use attached properties. In the case of the latter you'd create an attached property like this:
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}
And then you'd reference and override it like this in your XAML:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>
These are more-or-less the same, it's just that in the first case you're using existing properties already inside the control (or creating a new control that has them) whereas in the second case you're declaring and attaching them to an existing control externally.
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something likeGrid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.
– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
|
show 2 more comments
If the target control has dependency properties that you can use for those custom bindings then you can use TemplateBinding, here's an example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
Which you would then refer to like so:
<Grid>
<Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>
However, in the example you've given above you're using a Path and a Fill inside a template, which I'm guessing don't have associated properties. In this case your options are to either create a new control and add those properties to it or, preferably, use attached properties. In the case of the latter you'd create an attached property like this:
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}
And then you'd reference and override it like this in your XAML:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>
These are more-or-less the same, it's just that in the first case you're using existing properties already inside the control (or creating a new control that has them) whereas in the second case you're declaring and attaching them to an existing control externally.
If the target control has dependency properties that you can use for those custom bindings then you can use TemplateBinding, here's an example:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
Which you would then refer to like so:
<Grid>
<Button Style="{StaticResource ModifiedButtonStyle}" />
</Grid>
However, in the example you've given above you're using a Path and a Fill inside a template, which I'm guessing don't have associated properties. In this case your options are to either create a new control and add those properties to it or, preferably, use attached properties. In the case of the latter you'd create an attached property like this:
public static class ButtonProperties
{
public static Color GetMyForegroundColor(DependencyObject obj)
{
return (Color)obj.GetValue(MyForegroundColorProperty);
}
public static void SetMyForegroundColor(DependencyObject obj, Color value)
{
obj.SetValue(MyForegroundColorProperty, value);
}
// Using a DependencyProperty as the backing store for MyForegroundColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyForegroundColorProperty =
DependencyProperty.RegisterAttached("MyForegroundColor", typeof(Color), typeof(ButtonProperties), new PropertyMetadata(Colors.Black));
}
And then you'd reference and override it like this in your XAML:
<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Blue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="Some Text">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(behaviors:ButtonProperties.MyForegroundColor)}" />
</TextBlock.Foreground>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModifiedButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="behaviors:ButtonProperties.MyForegroundColor" Value="Red" />
</Style>
These are more-or-less the same, it's just that in the first case you're using existing properties already inside the control (or creating a new control that has them) whereas in the second case you're declaring and attaching them to an existing control externally.
edited Dec 30 '18 at 6:27
answered Dec 30 '18 at 6:18
Mark FeldmanMark Feldman
8,51311738
8,51311738
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something likeGrid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.
– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
|
show 2 more comments
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something likeGrid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.
– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
It looks very promising, but I will need some sleep before checking this. Thanks. :)
– Alan Wayne
Dec 30 '18 at 6:32
1
1
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Excellent! The syntax is completely new to me, but works perfectly. Thank you much!
– Alan Wayne
Dec 30 '18 at 20:08
Actually you've probably been using them all along without realizing. Whenever you add something like
Grid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.– Mark Feldman
Dec 30 '18 at 21:09
Actually you've probably been using them all along without realizing. Whenever you add something like
Grid.Row="0"
to a control...that isn't an internal property that every WPF control supports, it's an attached property that the Grid class creates and references (when present) during the layout process.– Mark Feldman
Dec 30 '18 at 21:09
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Sorry...Upon further work, the Data and Fill properties work correctly for each ModifiedButtonStyle. However, the controltemplate triggers only seem to work for the first defined button--no other button seems to respond visually to the triggers. Any suggestions?? Thanks. (Please see Edit#1).
– Alan Wayne
Dec 31 '18 at 4:04
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
Upon removing the TextBlock element from the BaseButtonStyle, the controltemplate triggers now work correctly for each button...Why??? Thanks. :)
– Alan Wayne
Dec 31 '18 at 4:21
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53975433%2fhow-to-use-basedon-to-template-a-toggle-button-in-generic-xaml%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown