Reputation: 13304
I'm working on a control. This control needs to be styled with input from an external source. I've looked for solutions and found a few that didn't break the code. However it is not styling the button. I set the style to the resources. Apply a reference to it on the button. Initialize the content, but the styles are not applied.
public MainPage()
{
//String[] settings = Application.Current.Resources["settings"].ToString().Split(new Char[1] { '\u003A' });
String[] settings = "_icons/pngp/2933.png:1:ff0000:Select files from disk...:36:36".Split(new Char[1] { '\u003A' });
//style the dialog button
ImageBrush image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(settings[0], UriKind.Relative));
Button dialogButton = new Button();
dialogButton.Background = image;
var styleOverride = new Style(typeof(Button)) ;
styleOverride.Setters.Add(new Setter(Border.CornerRadiusProperty, new CornerRadius(0)));
styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
this.Resources.Add("key", styleOverride);
dialogButton.Style = this.Resources["key"] as Style;
dialogButton.Height = double.Parse(settings[4]);
dialogButton.Width = double.Parse(settings[5]);
//attach the click handler;
dialogButton.Click += dialogButton_Click;
ToolTip tooltip = new ToolTip();
tooltip.Content = settings[3];
ToolTipService.SetToolTip(dialogButton, tooltip);
this.InitializeComponent();
this.LayoutRoot.Children.Add(dialogButton);
this.LayoutRoot.Drop += this.Canvas_Drop;
}
I've hardcoded the settings
string. Normally this is dynamic and comes from an external resource. The question is why is dialogButton.Style = this.Resources["key"] as Style;
not applying the desired style effects?
The image shows the result now (left) and the desired effect (right). No rounded border and a different border-color. And no, red isn't going to be the final color. It's for debugging.
Upvotes: 1
Views: 1549
Reputation: 39006
There are two issues in your code.
First, you are using Border.BorderBrushProperty
and Border.BorderThicknessProperty
which are not the dependency properties in Button
control. You should change them to Button.BorderBrushProperty
and Button.BorderThicknessProperty
respectively, like the following -
styleOverride.Setters.Add(new Setter(Button.BorderBrushProperty, colorConverter(settings[2])));
styleOverride.Setters.Add(new Setter(Button.BorderThicknessProperty, new Thickness(double.Parse(settings[1]))));
The second issue is that there's no CornerRadius
dependency property in a Button
control. So you can't simply change it to Button.CornerRadiusProperty
.
The workaround is, define a local Button
Style
inside your page, and then use TemplateBinding
to bind the CornerRadius
of the Border
(inside the ControlTemplate
of the Button
) to the Tag
dependency property. This part is easier to be done in xaml.
CornerRadius="{TemplateBinding Tag}"
And then, you just need to apply the Style
as the BaseOn
of your override Style
and update the Tag
property instead.
var styleOverride = new Style(typeof(Button))
{
BasedOn = (Style)this.Resources["ButtonStyle1"]
};
styleOverride.Setters.Add(new Setter(Button.TagProperty, new CornerRadius(0)));
Here attaches the full xaml Button
Style
.
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#CCFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#7FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#FF6DBDD1" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Background"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundAnimation"/>
<ColorAnimation Duration="0" To="#D8FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#C6FFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#8CFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
<ColorAnimation Duration="0" To="#3FFFFFFF" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="White" CornerRadius="{TemplateBinding Tag}">
<Grid Background="{TemplateBinding Background}" Margin="1" d:IsHidden="True">
<Border x:Name="BackgroundAnimation" Background="#FF448DCA" Opacity="0" d:IsHidden="True"/>
<Rectangle x:Name="BackgroundGradient" d:IsHidden="True">
<Rectangle.Fill>
<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#F9FFFFFF" Offset="0.375"/>
<GradientStop Color="#E5FFFFFF" Offset="0.625"/>
<GradientStop Color="#C6FFFFFF" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" d:IsHidden="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tested the code and the result is exactly what you expected.
Hope this helps!
Upvotes: 1
Reputation: 46
It seems like style is applyed, but red border overlays png. Try to comment out line:
/* styleOverride.Setters.Add(new Setter(Border.BorderBrushProperty, colorConverter(settings[2]))); */
Now background image become visible. Maybe solution is to resize image to 40x40 pixels with margins?
Upvotes: 0
Reputation: 20823
Do not set Style in code behind directly:
dialogButton.Style = this.Resources["key"] as Style;
but with SetValue
method:
var style = this.Resources["key"] as Style; // or this.TryFindResource("key") as Style;
dialogButton.SetValue(StyleProperty, style);
Upvotes: 0