wpf xaml checkbox template in style - wpf

first post so please go easy.
I am trying to get the value of a checkbox from another page (this is part of a navigation form in WPF project), but it always resets the value to false as soon as the page is changed. How do I get the IsChecked value to bind properly? I am learning just starting to work with WPF so the template is very basic, if there is a better way to do this then I am open to it.
Also the code behind page is vb.net not c# if that is going to play a part.
the style is called as follows:
<CheckBox Content="Photo" x:Name="OT_Photo" Grid.Row="0" Grid.Column="0" Style="{StaticResource ElementCheckbox}" />
There are several hundred checkboxes across these pages so I would very much like to avoid variables for each one.
The style is in 'Application.xaml'
<Style TargetType="CheckBox" x:Key="ElementCheckbox">
<Setter Property="IsThreeState" Value="True" />
<Setter Property="IsChecked" Value="{Binding IsChecked ,Mode=TwoWay}" />
<Setter Property="Foreground" Value="Navy" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="15,4,0,4" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="MaxWidth" Value="500" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<DockPanel DockPanel.Dock="Left">
<Border x:Name="Border" CornerRadius="0" VerticalAlignment="Top">
<Image Height="20" Width="20" Name="CheckMark" />
</Border>
<TextBlock x:Name="CheckText" Text="{TemplateBinding Content}" Margin="5,0,0,0" FontSize="{TemplateBinding FontSize}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" />
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter TargetName="CheckMark" Property="Source" Value="CheckBoxNull.png" />
</Trigger>
<Trigger Property="IsChecked" Value="false">
<Setter TargetName="CheckMark" Property="Source" Value="CheckBoxCross.png" />
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="CheckMark" Property="Source" Value="CheckBoxTick.png" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" TargetName="Border">
<Setter.Value>
<DropShadowEffect ShadowDepth="1" Color="Blue" Opacity="1" BlurRadius="2"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Blue" TargetName="CheckText" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks in advance of any help!
I should add I have been stuck on this for over a day, I have tried template binding, binding paths, and an on click procedure based on the c# answers I have found already. always resulting in the checkbox being reset though.

Solved
My problem was unrelated to the checkbox as it happened, the page was not named statically so the properties always served the default values. (rookie mistake - much shame)
on the up side the code above works perfectly (in its limited way) if anyone wants to pinch it!
VB.NET:
Private Sub MainForm_Loaded(sender As Object, e As RoutedEventArgs) Handles MainForm.Loaded
Me.NavigationService.Navigate(ContactDetailsPage)
End Sub
instead of XAML stating the source:
<NavigationWindow x:Name="MainForm" x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="" Source="ContactDetails.xaml">

I think the problem is that you define your binding in your template instead in your control. You usually don't do bindings in your templates unless it is a DataTemplate.
<CheckBox IsChecked="{Binding Value}" Content="Photo" x:Name="OT_Photo" Grid.Row="0" Grid.Column="0" Style="{StaticResource ElementCheckbox}" />
Don't forget to set de DataContext for your object.
You might want to test the binding first without templating. If this doesn't solve your problem it might be useful to post the code-behind as well.

Related

WPF Validation ErrorTemplate errorcontent tooltip not working

I'm not sure if I'm missing something simple or not. I'm thinking maybe a binding needs to change possibly? Or maybe its not properly targeting the TextBox for the ErrorContent?
I think it's worth noting that neither example produces a binding error.
If I have the below XAML defined in my App.xml, when my field is validated, everything looks like it should be working, but the tooltip is not working because ErrorContent seems to be blank, if I change that binding in the tooltip to "Test" the tooltip shows "Test".
<Style BasedOn="{StaticResource DefaultTextBoxStyle}" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Image
Height="24"
Margin="-28,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
DockPanel.Dock="Right"
Source="/Resources/error-96.png"
ToolTip="{Binding /ErrorContent}" />
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I add to that same XAML some triggers to set the border colors etc, the tooltip then magically starts working, seen below.
<Style BasedOn="{StaticResource DefaultTextBoxStyle}" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border
x:Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
UseLayoutRounding="True">
<ScrollViewer
x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Trigger.Setters>
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="3" />
</Trigger.Setters>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Validation.HasError" Value="false" />
<Condition Property="IsMouseOver" Value="true" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
</MultiTrigger.Setters>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="border" Property="Opacity" Value="0.56" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Image
Height="24"
Margin="-28,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
DockPanel.Dock="Right"
Source="/Resources/error-96.png"
ToolTip="{Binding /ErrorContent}" />
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Incase you want to see the textbox binding, which works to show the ErrorTemplate.
<TextBox
Margin="0,2.5,2.5,2.5"
HorizontalAlignment="Stretch"
ui:ControlHelper.PlaceholderText="IPv4 Address"
ui:TextBoxHelper.IsDeleteButtonVisible="False"
Text="{Binding EditServerModel.IPAddress, ValidatesOnDataErrors=True}" />
My main reason for not wanting to use the second one is it replaces the template of the DefaultTextBoxStyle and breaks the placerholder text in the textboxes, along with some other special features, all I really want/need is the part that shows the error image with a tooltip.
Edit:
I'm using CommunityToolkit.MvvM. My models implement ObservableValidator, which implements INotifyDataErrorInfo. My properties in my models use DataAnnotation attributes such as [Required] and [RegularExpression]
An example:
public class ServerModel : ObservableValidator
{
private string _iPAddress;
[Required]
[RegularExpression(#"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$", ErrorMessage = "Not a valid IPv4 address.")]
public string IPAddress
{
get => _iPAddress;
set
{
SetProperty(ref _iPAddress, value);
ValidateProperty(value);
}
}
}
Edit - Working answer:
I ended up copying the default style from the ModernWpf project and removing primitives:ValidationHelper.IsTemplateValidationAdornerSite="True" so that I could use my own validation template.
Try this binding:
ToolTip="{Binding [0].ErrorContent}"
It this doesn't work, the issue is related to the DefaultTextBoxStyle.

Editing a MahApps Metro Circle Toggle button

I know there are a few questions surrounding the MahApps Metro styles, but i haven't found one that address the issue I am having.
I have an app that I am maintaining, a lot of which I helped build, using a central style XAML repository.
A part that I didn't build uses the style for the Metro Circle Toggle Button from MahApps. According to my Stakeholders, I need to change the selected state to be more contrasting from the normal state of the button. However I haven't been able to find where to go to access that style in my application.
My gut instinct is to create a complete style in my repository that replaces the Metro Style, but I figured I would ask around to see if anyone here could help me.
Any Hints wold be greatly appreciated.
Update 1:
I tried to use the BasedOn property to keep the amount of code down. I then set the background color to switch from black to white when "IsChecked" is True.
here is the code i added:
<Style x:Key="CustomCircleToggleButtonStyle"
TargetType="{x:Type ToggleButton}"
BasedOn="{StaticResource MetroCircleToggleButtonStyle}">
<Setter Property="Background" Value="{StaticResource DarkBorder}"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True" >
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
Unfortunately, there is some animation form the MahApps sinking through that makes the button go from the black, immediately to white then fade to the dark blue color that i am trying to get rid of.
Here is the wpf toggle button:
<ToggleButton Width="50" IsEnabled="{Binding IsMultipleSelected,Converter= {StaticResource BooleanNegate}}"
Height="50"
Style="{DynamicResource CustomCircleToggleButtonStyle}"
Command="{Binding Path=GroupSelectCommand}"
IsChecked="{Binding IsLasoSelected}">
<Rectangle Width="20"
Height="20"
Fill="{DynamicResource IconButtonActiveBorder}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill"
Visual="{DynamicResource appbar_lasso}" />
</Rectangle.OpacityMask>
</Rectangle>
</ToggleButton>
I am hoping to move a lot of this into the style, but I have to keep functional.
Right, so the reason it's not working with your example is you can't overwrite triggers that interact with ControlTemplate via Triggers from the Style....
So, if we go take a peek at line 615 here (which btw, I assume there's a file in your metro stuff named the same) we see inside the template the ControlTemplate.Triggers which on IsChecked is changing the opacity of ellipsebg ellipse. It in turn is hard set to fill of {DynamicResource AccentColorBrush}...
So...you could overwrite that brush at the instance level....or, just go edit the full style template to use a different brush all together.
In other words you could go change line 630 of Fill="{DynamicResource AccentColorBrush}" to another brush or brush resource and it would inherit to each instance (that would be my choice to keep centrally maintainable properties).
Or, at the instance something like:
<StackPanel>
<StackPanel.Resources>
<SolidColorBrush x:Key="AccentColorBrush">Red</SolidColorBrush>
<Style TargetType="ToggleButton"
BasedOn="{DynamicResource CustomCircleToggleButtonStyle}"/>
</StackPanel.Resources>
<ToggleButton/>
<ToggleButton/>
<ToggleButton/>
</StackPanel>
Make sense? :)
To close the loop, and post my answer for everyone else with the issue, I ended up creating a style that i put in my style repository. I think my Solution might be a little unique though as i don't actually have access the the MahApps.Metro source code in my solution.
Here is what I did:
<Style x:Key="CircleButton" TargetType="ToggleButton">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource MyFocusVisual}"/>
<Setter Property="Margin" Value="2 2 2 2"/>
<Setter Property="Width" Value="45"/>
<Setter Property="Height" Value="45"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Ellipse x:Name="BorderCircle">
<Ellipse.Fill>
<SolidColorBrush Color="SlateGray"/>
</Ellipse.Fill>
</Ellipse>
<Ellipse x:Name="BodyCircle" Margin="3" >
<Ellipse.Fill >
<SolidColorBrush Color="Black"/>
</Ellipse.Fill>
</Ellipse>
<Rectangle x:Name="Mask"
Width="20"
Height="20"
Fill="{DynamicResource IconButtonActiveBorder}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill"
Visual="{DynamicResource appbar_lasso}" />
</Rectangle.OpacityMask>
</Rectangle>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="BodyCircle" Property="Fill" Value="White"/>
<Setter TargetName="BorderCircle" Property="Fill" Value="Black"/>
<Setter TargetName="Mask" Property="Fill" Value="Black"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="BodyCircle" Property="Fill" Value="DarkOrange"/>
<Setter TargetName="BorderCircle" Property="Fill" Value="Black"/>
<Setter TargetName="Mask" Property="Fill" Value="Black"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This gives me total control of all aspects of the toggle button and the identical look as it had before. All i have to do to implement it is call it from the WPF view:
<ToggleButton IsEnabled="{Binding IsMultipleSelected,Converter={StaticResource BooleanNegate}}"
Style="{DynamicResource CircleButton}"
Command="{Binding Path=GroupSelectCommand}"
IsChecked="{Binding IsLasoSelected}">
</ToggleButton>
Hope this helps others out.

Simple working example to override default visual style of a button in wpf

I want to create custom visual style for my buttons.
I need a simple working example of how to override default visual style of a button. As well as a simple explanation of how to apply it.
I want to get something working, so I can start from there and experiment my way further.
I've tried to add a new recourse dictionary as follows:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="mstyle" TargetType="Button">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ResourceDictionary>
after that I've created some new button in runtime and tried to apply this style to it:
Dim MyButton As New Button
Dim st As New Style
st = Application.Current.FindResource("mstyle")
MyButton.Style = st
When I try to run this, I get an error that the recourse 'mstyle' could not be found.
You don't in most cases need any code behind to do that all what you need is to define a custom style that target your button in the resource dictionary or in the window resource here an example :
<Style x:Key="DarkStyleButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="#373737" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<Grid>
<ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#E59400" />
<Setter Property="Foreground" Value="White" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
first set the value for the properties you want to customize,
then set the button template and don't forget to add the
ContentPresenter that will hold the button content
finally define triggers to handle the mouse over, click and what ever
else you want to set a custom look when it triggers (for example the
desable/enabled )
To use that style here how
<Button x:Name="BrowseButton" Margin="5" Style="{StaticResource DarkStyleButton}" ToolTip="tooltip about the button">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="../BrowseImage.png"/>
<TextBlock Text="Browse" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5"></TextBlock>
</StackPanel>
</Button.Content>
</Button>

custom button with inconsistent visibility

The EditCommandButton style defined below is showing odd behavior; it only shows for the last instance defined (next to the Avatar label below).
I tried making the style x:Shared="true" and using DynamicResource but with the same result.
I do eventually want the button to invisible until request, which is why you see a trigger for that. But until I figure this out I just have the default visibility at visible.
Can someone explain this behavior and offer a fix?
Cheers,
Berryl
Design View
Runtime View
Button Style
<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="a" Foreground="Navy" FontWeight="Bold" FontFamily="Wingdings 3" FontSize="24" Width="30"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="theBorder" Background="Transparent" CornerRadius="4">
<ContentPresenter x:Name="theContent" Visibility="Visible" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
<Setter TargetName="theBorder" Property="Background" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Command" Value="{Binding SelectedSatelliteVm.EditCommand}"/>
</Style>
Usage
<DataTemplate x:Key="PersonInfoEditingControlTemplate">
<Grid>
...
<Label Grid.Column="0" Grid.Row="0" ... />
<Button Style="{StaticResource EditCommandButtonStyle}" Grid.Column="1" Grid.Row="0"/>
<TextBlock .../>
<Label Grid.Column="0" Grid.Row="1" ... />
<Button Style="{StaticResource EditCommandButtonStyle}" Grid.Column="1" Grid.Row="1"/>
<TextBlock .../>
<TextBlock Grid.Column="0" Grid.Row="2" .../>
<Button Style="{StaticResource EditCommandButtonStyle}" Grid.Column="1" Grid.Row="2"/>
<Image Grid.Column="2" Grid.Row="2" ... />
</Grid>
</DataTemplate>
EDIT for Rachel
Look Ma, no triggers! Only the last button shows the arrow though...
<Style x:Key="TestCommandButtonStyle" TargetType="{x:Type Button}" >
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="a" Foreground="Navy" FontWeight="Bold" FontFamily="Wingdings 3" FontSize="24" Width="30"/>
</Setter.Value>
</Setter>
<Setter Property="Command" Value="{Binding SelectedSatelliteVm.EditCommand}"/>
</Style>
the FIX
<Style x:Key="EditCommandButtonStyle" TargetType="{x:Type Button}" >
<Setter Property="Content" Value="a" />
<Setter Property="Foreground" Value="Navy" />
<Setter Property="FontFamily" Value="Wingdings 3" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Width" Value="30" />
<Setter Property="Height" Value="Auto" />
<Setter Property="Command" Value="{Binding SelectedSatelliteVm.EditCommand}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="theBorder" CornerRadius="4">
<ContentPresenter x:Name="theContent" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter TargetName="theContent" Property="Visibility" Value="Hidden"/>
<Setter TargetName="theBorder" Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="theContent" Property="Visibility" Value="Visible"/>
<Setter TargetName="theBorder" Property="Background" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The style as originally written actually had two problems, both fixed by the style above. (by fixed I mean it works as intended, not that it is the 'right' way to do it!):
DP Precedence - this is what Rachel's answer is addressing although her answer. But the only effective fix I found is to set visibility using two triggers for IsMouseOver as shown.
Only the last item in the Grid was showing any content! - this one makes no sense to me, but moving the properties previously in the TextBlock content to Setters on the style fixes that.
Dependencey properties defined in the <Tag> have a higher precedence than items defined in triggers, so will always overwrite them.
For example, in this case the button's Visibility will always be Collapsed regardless of what the trigger is, because the property is defined in the <Button> tag
<Button Visibility="Collapsed">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Property="{Binding SomeValue}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
To make this trigger work, move the Visibility property to a Style Setter, which has a lower precedence than a Style Trigger, so triggered values will overwrite it
<Button>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Property="{Binding SomeValue}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
See MSDN's Dependency Property Precedence List for more information
Edit
As for your second problem about the Content only showing up once, I suspect it is because you have the Content bound in your style, and not the ContentTemplate.
WPF is creating a single instance of the TextBlock arrow, and a control can only have one parent, so after the style is applied, so only one Button can contain the arrow TextBlock
The fix is to use the ContentTemplate property instead of the Content property.
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="a" Foreground="Navy" FontWeight="Bold" FontFamily="Wingdings 3" FontSize="24" Width="30"/>
</DataTemplate>
</Setter.Value>
</Setter>
Honestly, I'm surprised it didn't give you an error about Specified element is already the logical child of another element. That is usually what happens in these kind of cases (see my post here for more details)

What's the best way to handle layout issues with multi-language support in WPF/XAML?

I'm creating a standalone WPF app with multi-language support. I've found some great resources (mostly on SO) on how to store and access the strings as needed. This part is pretty straightforward and doable, but I'm fuzzy on how to take care of screen layout issues.
I'm using some custom images to skin up my app for buttons, etc. For instance, here's a button with some text within:
<Button
Canvas.Left="33"
Canvas.Top="484"
Style="{StaticResource SmallButtonBase}">
<TextBlock
FontSize="20"
FontWeight="Bold"
TextAlignment="Center" FontFamily="Helvetica">
Enter
</TextBlock>
</Button>
Now here is the same button with text from another language:
<Button
Canvas.Left="33"
Canvas.Top="484"
Style="{StaticResource SmallButtonBase}">
<TextBlock
FontSize="20"
FontWeight="Bold"
TextAlignment="Center" FontFamily="Helvetica">
Enterenschtein
</TextBlock>
</Button>
So my question is: What is a good method to prevent this "overflow" situation. I'd like to have XAML take care of any font resizing or indenting that is needed automatically so that I don't have to tweak the UI for each language I'm supporting.
Any insight is appreciated!
p.s. Here's the XAML for SmallButtonBase. It basically defines what happens when the button has focus or is pressed. A different image is used for each case.
<Style x:Key="SmallButtonBase" TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="Container">
<Image x:Name="Img" Source="/Resources/Elements/Buttons/10.png" Margin="6" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Img" Property="Source" Value="/Resources/Elements/Buttons/11.png" />
<Setter TargetName="Img" Property="Margin" Value="0" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsKeyboardFocused" Value="True" />
<Condition Property="IsPressed" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Img" Property="Source" Value="/Resources/Elements/Buttons/12.png" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try putting a viewbox around your contentpresenter with a fixed width and height that matches your image for the button
like this
<Viewbox Width="85" Height="85">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Viewbox>
I think then you can allow WPF to scale the font to fit in that location.

Resources