I have an application where a number of custom buttons are dynamically generated within a WrapPanel. All works fine and I am able to assign border thickness, ImageSource, Content etc. as I generate the buttons in code. The customer now has a requirement to allow them to choose border colours for individual buttons and try as I might I cannot figure out the correct binding scenario. I'm on a steep WPF learning curve here so it may be that my initial design is somewhat off kilter.
In my Generic.XAML I have the button specified thus:
<Style TargetType="{x:Type local:LauncherButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:LauncherButton}">
<Border Name="LauncherButtonBorder" BorderThickness="{TemplateBinding BThickness}"
CornerRadius="10" Background="White" >
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="SteelBlue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="PaleGoldenrod" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<DockPanel LastChildFill="True" Background="White" Margin="3">
<TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="Center"
Foreground="{DynamicResource TaskButtonTextBrush}" FontWeight="Bold"
Margin="5,0,0,0" VerticalAlignment="Center" FontSize="10"
Background="Transparent" DockPanel.Dock="Bottom" TextWrapping="Wrap" />
<Image Source="{TemplateBinding ImageSource}" Stretch="Uniform" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I want to dynamically change in c# the border colours that are currently set to static SteelBlue and PaleGoldenrod.
The button class is defined thus:
public class LauncherButton : ButtonBase
{
static LauncherButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LauncherButton), new FrameworkPropertyMetadata(typeof(LauncherButton)));
}
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public Thickness BThickness
{
get { return (Thickness) GetValue(BThicknessProperty); }
set { SetValue(BThicknessProperty,value);}
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(LauncherButton), new UIPropertyMetadata(null));
public static readonly DependencyProperty BThicknessProperty =
DependencyProperty.Register("BThickness", typeof(Thickness), typeof(LauncherButton), new UIPropertyMetadata(null));
}
and I'm binding some of the properties to an instance of the following class:
public class CustomButton:INotifyPropertyChanged
{
private string _type;
private string _buttonId;
private string _name;
private string _image;
private string _link;
private string _parent;
private List<CustomButton> _children;
private bool _isExpanded;
private bool _isSelected;
public string ButtonId
{
get { return _buttonId; }
set
{
if (value == _buttonId) return;
_buttonId = value;
OnPropertyChanged("ButtonId");
}
}
public string Type
{
get { return _type; }
set
{
if (value == _type) return;
_type = value;
OnPropertyChanged("Type");
}
}
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
public string Image
{
get { return _image; }
set
{
if (value == _image) return;
_image = value;
OnPropertyChanged("Image");
}
}
public string Link
{
get { return _link; }
set
{
if (value == _link) return;
_link = value;
OnPropertyChanged("Link");
}
}
public string Parent
{
get { return _parent; }
set
{
if (value == _parent) return;
_parent = value;
OnPropertyChanged("Parent");
}
}
public List<CustomButton> Children
{
get { return _children; }
set
{
if (Equals(value, _children)) return;
_children = value;
OnPropertyChanged("Children");
}
}
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (value.Equals(_isExpanded)) return;
_isExpanded = value;
OnPropertyChanged("IsExpanded");
}
}
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value.Equals(_isSelected)) return;
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Are you trying to make the two brushes used for Border.BorderBrush
dynamic?
If so you can address it in a few ways.
LauncherButton
for say NormalBorderBrush
and MouseOverBorderBrush
and then set it as you wish when you use the Button
. Now to get the Border
to use this, within it's Style where you set SteelBlue
or PaleGoldenRod
, apply a RelativeSource FindAncestor
binding with AncestorType
as local:LauncherButton
and point it to the corresponding Brush(NormalBorderBrush
or MouseOverBorderBrush
)Example:
public class LauncherButton : ButtonBase {
...
public static readonly DependencyProperty NormalBorderBrushProperty =
DependencyProperty.Register("NormalBorderBrush", typeof(Brush), typeof(LauncherButton),
new UIPropertyMetadata(Brushes.Blue));
public static readonly DependencyProperty MouseOverBorderBrushProperty =
DependencyProperty.Register("MouseOverBorderBrush", typeof(Brush), typeof(LauncherButton),
new UIPropertyMetadata(Brushes.Red));
public Brush NormalBorderBrush
{
get { return (Brush)GetValue(NormalBorderBrushProperty); }
set { SetValue(NormalBorderBrushProperty, value); }
}
public Brush MouseOverBorderBrush
{
get { return (Brush)GetValue(MouseOverBorderBrushProperty); }
set { SetValue(MouseOverBorderBrushProperty, value); }
}
}
in xaml:
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:LauncherButton}},
Path=NormalBorderBrush}" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:LauncherButton}},
Path=MouseOverBorderBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
and usage:
<local:LauncherButton BThickness="5"
Content="Hellooooo"
MouseOverBorderBrush="Green"
NormalBorderBrush="Aqua" />
Sample Download - This does not contain the converter for Brush usage, that should be easy enough to implement.
BorderBrush
property which it already has and apply this to the Border with a TemplateBinding BorderBrush
. Now this would mean you need to switch the BorderBrush
accordingly when your IsMouseOver
state change occurs.Style
and getting a reference to the Border
element by finding it via it's Name and then tweaking it at run-time.Personally I'd opt for option 1. Finally use a converter or likewise in the Binding to make it MVVM friendly.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments