I am a relatively new user of WPF and have run into a problem regarding dynamic Button generation and Buttons' default hover properties.
I am currently working on an application where a significant number of buttons are being generated on a Canvas in the code behind. The contents of each button are unique images referenced by an array of objects containing Uri strings. This array is populated by reading in a file containing these Uri strings, so the number and placement of buttons on this canvas vary based on which file is being read.
For the most part, the appearance of the Canvas when the application runs is what was intended, however hovering over any of the Buttons replaces the image with the default blue background for the duration that the mouse overlaps.
Here is an example of the code that I am using to generate the buttons:
exampleButton = new Button { Content = "Name", Width = 50, Height = 65, Background = new ImageBrush(new BitmapImage(new Uri(@object.UriString, UriKind.Relative))) };
exampleButton.Style = exampleStyle;
exampleCanvas.Children.Add(exampleButton);
Please understand that I have omitted pieces of code irrelevant to my question.
Here is an example of the style that was used, also in the code behind:
exampleStyle = new Style(typeof(Button));
exampleStyle.Setters.Add(new Setter(Button.ForegroundProperty, Brushes.Transparent));
exampleStyle.Setters.Add(new Setter(Button.BorderBrushProperty, Brushes.Transparent));
Together these achieve the effect I am trying to create, barring hover behavior.
So far I have tried appending ControlTemplate overrides into the style declaration but am unsure of how that translates from XAML to the C# code behind. I have also tried creating and binding button templates created in the XAML but I haven't had success in finding explanations or tutorials that apply to my situation.
Any help to accomplish this via the code behind would be greatly appreciated. Of course, if I'm doing this really unconventionally and there is a more standard way of doing things I am all ears.
EDIT: This is the XAML I am using to declare the style that my dynamically generated buttons are using.
<Style x:Key="MySuperButtonStyle" TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="65" />
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
Using this call to assign the style in the code behind:
exampleButton.Style = (Style)FindResource("MySuperButtonStyle");
This is happening because the default Button
control style has a trigger that changes the Background
property of the button when the mouse hovers over it. You need to use a custom style for the button:
<Style x:Key="MySuperButtonStyle" TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="65" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here the width and the height are set using the style, so you no longer need to set those properties in code. The control template has been changed so it consists only of a Border
element with the content inside of it. There are no triggers at all, so the button won't change its appearance when clicked or hovered over.
In your code all you need to do is obtain a reference to this style then assign that to the Style
property when you are creating the button.
Having said all this, in WPF you rarely need to create controls in code. Instead you should really be using the MVVM (Model-View-ViewModel) pattern and data binding. You probably shouldn't be creating styles and setters in code either.