WPF button textwrap style - wpf

How do I change the default textwrapping style of a button in WPF?
The obvious solution of:
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="TextWrapping" Value="Wrap"></Setter>
</Style>
doesn't work, because Textwrapping isn't a settable property here, apparently.
If I try:
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="{Binding}" Foreground="White" FontSize="20" FontFamily="Global User Interface" TextWrapping="Wrap"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I just get a worthless response from the compiler:
Error 5 After a 'SetterBaseCollection' is in use (sealed), it cannot be modified.
Removing the ControlTemplate tag keeps the error.
The following attempt yields a different error:
<Setter Property="TextBlock">
<TextBlock Text="{Binding}" Foreground="White" FontSize="20" FontFamily="Global User Interface" TextWrapping="Wrap"/>
</Setter>
Error 5 The type 'Setter' does not support direct content.
I see that I can set the textwrapping for each button individually, but that's pretty asinine. How can I do it as a style? What are the magic words?
And for future reference, where can I find a list of these magic words, so I can just do this on my own? The MSDN entry is pretty useless when I try to find out about which properties can be set by the setter.

To expand Eric's answer with an example:-
<Button Name="btnName" Width="50" Height="40">
<TextBlock Text="Some long text" TextWrapping="Wrap" TextAlignment="Center"/>
</Button>

I solved this problem by adding a TextBlock to the button, and using it to display the button text instead of the button's Content property. Be sure to set the TextBlock's height property to Auto, so that it grows in height to accommodate the number of lines of text as it wraps.

Your second version should work, and does for me, with the caveat that you need to change the TextBlock Text binding:
<!-- in Window.Resources -->
<Style x:Key="fie" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="{TemplateBinding Content}" FontSize="20" TextWrapping="Wrap"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- then -->
<Button Style="{StaticResource fie}">verylongcaptiongoeshereandwraps/Button>
Note this completely replaces the button style (i.e. you will need to create your own button chrome if you want it).
Regarding your second question, all writeable dependency properties can be set using a Setter. The reason you were unable to set TextWrapping on a Button via a style is that Button does not have a TextWrapping dependency property (or indeed any TextWrapping property). There are no "magic words," just the names of dependency properties.

<Style TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{TemplateBinding Content}" TextWrapping="Wrap" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>

Here's an example of Eric's answer in C# code-behind:
var MyButton = new Button();
MyButton.Content = new TextBlock() {
FontSize = 25,
Text = "Hello world, I'm a pretty long button!",
TextAlignment = TextAlignment.Center,
TextWrapping = TextWrapping.Wrap
};

To expand #Rob's answer with #fadden's comment:
<Button Width="50" Height="40">
<AccessText Text="_Some long text" TextWrapping="Wrap" TextAlignment="Center"/>
</Button>
The TextBlock control does not support keyboard hotkeys (_).

Related

Control Error icon showing twice after styling

I'm applying this style to an infragistics control XamDateTimeEditor.
The new error icon displays as expected.
issue: The original error style is still displaying when a validation error occurs. Thus making the control to have two error icon styles.
<Style TargetType="{x:Type XamDateTimeEditor}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<DockPanel>
<Border
Background="Red"
Width="25"
Height="25"
CornerRadius="10"
>
<TextBlock
Text="Error"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontWeight="Bold"
Foreground="White"
/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using a view model that implements IDataErrorInfo is the best approach when customizing an error template that targets XamDateTimeEditor.
This was previously discussed and demonstrated on our forums at: http://www.infragistics.com/community/forums/t/109152.aspx
https://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/

How to apply different content to a single property in style located in Resource Dictionary?

I have 2 textboxes which using AddItemTextBoxStyle:
<TextBox x:Name="txtItemA" Style="{StaticResource AddItemTextBoxStyle}"></TextBox>
<TextBox x:Name="txtItemB" Style="{StaticResource AddItemTextBoxStyle}"></TextBox>
Inside the AddItemTextBoxStyle (which is a style in Resource Dictionary), I have a tag property which sets the watermark text within the textbox:
<Style x:Key="AddItemTextBoxStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource CustomTextBoxStyle}">
<Setter Property="Tag" Value="Type here" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBlock Style="{StaticResource WaterMarkTextStyle}" x:Name="WaterMarkLabel" Text="{TemplateBinding Tag}" />
</ControlTemplate>
</Setter.Value>
</Setter.Property>
</Style>
By default, the watermark text is "Type here". However, if I want the watermark text to be different in the two textboxes, for example:
Textbox txtItemA - "Type Item A here"
Textbox txtItemB - "Type Item B here"
May I know how can I do this? Since the style is located in resource dictionary.
I try to search online but still unable to find a clue for it.
<TextBox x:Name="txtItemA" Style="{StaticResource AddItemTextBoxStyle}" Tag="Some wathermark" />
<TextBox x:Name="txtItemB" Style="{StaticResource AddItemTextBoxStyle}" Tag="Another watermarks" />
notice, that your style just sets default value of tag. Actual value is set in control instance and template binding takes the value from instance, not from style.

The button's bordesr are invisiable and no background color

Originally I had a button and worked well. Now I want to make the corners round.
<Button Content="Start" x:Name="Start" Style="{StaticResource RoundButtonTemplate}"
HorizontalAlignment="Left"
Margin="20,20,0,0"
VerticalAlignment="Top"
Width="75"
Click="Start_Click">
In code behind, I set the background color as:
Start.IsEnabled = false;
Start.Background = Brushes.Red;
In App.xaml:
<Application.Resources>
<Style x:Key="RoundButtonTemplate" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="15" BorderThickness="1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Now the questions are:
The background color is gone.
The borders of the button are invisible.
How to modify the style?
Have a look at the default style of a button http://msdn.microsoft.com/de-de/library/ms753328%28v=vs.110%29.aspx
In your style you define a "border" with a corner radius, but no way to retrieve the color. You should add a Background attribute with {TemplateBinding Background} so that it binds to the Background attribute of your button (Start.Background).
You can always copy the default style and modify it. Also you should have a look at how template bindings work :)

Focus image does not work for first time on Textbox

i want to show a focus image around a text box when it got focus. so i create following style
<Style x:Key="TextBoxFocusVisualStyle">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Image Source="/WPFApp;component/Resources/txtFocus.png" Stretch="Fill" Margin="-8,-6,-8,-6"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and in window xaml file i used this style as following
<TextBox Grid.Column="1" Height="34" Margin="186,48,0,0" Name="txtEmailId" VerticalAlignment="Top" KeyboardNavigation.TabIndex="0" MaxWidth="293" HorizontalAlignment="Left" Width="293" Text="" FocusVisualStyle="{DynamicResource TextBoxFocusVisualStyle}"/>
but problem is that it does not work during loading. When window load then initially focus is on that textbox and at that time it does not show the image .However when i navigate to other textbox (and other control) then it show focus image. and finally when i focus return to that textbox then it display the focus image
so problem is that it does not show focus image first time on when window loaded. Please suggest that where i am wrong.
Consider that FocusVisualStyle applies to a control only when focused by keyboard (TAB key).
This is different from the logical focus that you obtain for example using
Control.SetFocus()
For an overview on Focus have a look at
http://msdn.microsoft.com/en-us/library/aa969768.aspx
A possible workaround for your problem is work with DependencyProperty IsFocused an use Style instead of FocusVisualStyle
<Style x:Key="TextBoxStyle" TargetType="{x:Type Control}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Image Stretch="Fill" Margin="-8,-6,-8,-6" Source="/WPFApp;component/Resources/txtFocus.png" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
And then in the main Window
<TextBox Grid.Column="1" Height="34" Margin="186,48,0,0" Name="txtEmailId"
VerticalAlignment="Top" KeyboardNavigation.TabIndex="0" MaxWidth="293"
HorizontalAlignment="Left" Width="293" Text=""
Style="{DynamicResource TextBoxFocusVisualStyle}" Background="White" />
Hope this heps

How to change TextBlock default properties for a ContentPresenter in a template

Based on the following code :
<GroupBox>
<GroupBox.Template>
<ControlTemplate TargetType="{x:Type GroupBox}">
<ContentPresenter TextElement.FontSize="28" />
</ControlTemplate>
</GroupBox.Template>
<TextBlock>Test</TextBlock>
</GroupBox>
I was expecting "Test" to be displayed with FontSize=28. But it uses the default size instead.
If I remove the TextBlock like this :
<GroupBox>
<GroupBox.Template>
<ControlTemplate TargetType="{x:Type GroupBox}">
<ContentPresenter TextElement.FontSize="28" />
</ControlTemplate>
</GroupBox.Template>
Test
</GroupBox>
The text is now the displayed with 28 as FontSize.
Shouldn't the property value be inherited when I use a TextBlock ?
This other question How do I Change the FontFamily on a ContentPresenter? doesn't help, as it works only for default content too.
This question also : How do I Change the FontFamily on a ContentPresenter?.
Both works whe you use the default content handler, but fails when you manually create a textblock.
Edit: As demonstrated in this other question, I've tried by simply using a ContentControl :
<StackPanel>
<StackPanel.Resources>
<ControlTemplate x:Key="UsingBorderTemplate" TargetType="{x:Type ContentControl}">
<Border BorderBrush="Red" BorderThickness="1" TextElement.FontFamily="Courier New" Margin="5">
<ContentPresenter/>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="MyTemplate" TargetType="{x:Type ContentControl}">
<ContentPresenter TextElement.FontFamily="Courier New" Margin="5" />
</ControlTemplate>
</StackPanel.Resources>
<ContentControl Template="{StaticResource MyTemplate}">
I'm courier new!
</ContentControl>
<ContentControl Template="{StaticResource MyTemplate}">
<TextBlock>I'm default!</TextBlock>
</ContentControl>
</StackPanel>
You can change the template from "MyTemplate" to "UsingBorderTemplate" with the same result.
I had an odd problem with ContentPresenter. I remember that I have analyzed the source of the problem and have found out that it was by design - Probably you have here the same issue.
Look at this post, maybe it helps you.
I think the text that the content presenter is presenting is the GroupBox.Header, and you may just be tacking another TextBox in there that isn't part of the Group Box.
In your first code block, add the line below and see if that works:
<GroupBox.Header>Test</GroupBox.Header>
HTH,
Berryl

Resources