WPF CheckBox style with the TextWrapping - wpf

I need to apply a TextWrapping in the WPF CheckBox.
Please look at this two samples:
<CheckBox>
<TextBlock TextWrapping="Wrap"
Text="_This is a long piece of text attached to a checkbox."/>
</CheckBox>
<CheckBox>
<AccessText TextWrapping="Wrap"
Text="_This is a long piece of text attached to a checkbox."/>
</CheckBox>
If I use a TextBlock in the Content of the CheckBox, the check element (vertical alignment is top) and the text displays properly, but not the accelerator.
If I use an AccessText in the Content of the CheckBox, the check element displays wrong (vertical alignment is center).
How can I change the Style of the elements to display this CheckBox correct?

If you combine the two you will probably get the effect you desire.
<CheckBox>
<TextBlock>
<AccessText TextWrapping="Wrap"
Text="_This is a long piece of text attached to a checkbox."/>
</TextBlock>
</CheckBox>

Use VerticalContentAlignment to align the box to the top. Use Padding to adjust text position.
<CheckBox VerticalContentAlignment="Top" Padding="2,-2,0,0">
<AccessText Text="_This is a long piece of text attached to a checkbox." TextWrapping="Wrap"/>
</CheckBox>

Havew you tried setting an implicit style for the AccessText, or just an AccessText style you can apply?
Here's an implicit style that would work:
<Style x:Key="{x:Type AccessText}"
TargetType="{x:Type AccessText}"
BasedOn="{x:Null}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Margin" Value="5,2"/>
<Setter Property="Text" Value="AccessText"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
If you include this in your project the AccessText should work the way you want. If you need something else, adjust the style.
If you don't want all AccessTexts to behave this way, name the style and apply it where you use it:
<CheckBox>
<AccessText TextWrapping="Wrap" Style="{DynamicResource CkbxAccessTextStyle}"
Text="_This is a long piece of text attached to a checkbox."/>
</CheckBox>

Related

Setting text color in ComboBoxItem

I want to set the text color for PASS as GREEN and the text color for FAIL as RED. I can't seem to find the solution. I need to do this in pure XAML.
<ComboBox x:Name="LocatedCorrectly" Width="100"
Height="25" Grid.Column="1" Grid.Row="2"
HorizontalAlignment="Left"
IsSynchronizedWithCurrentItem="True">
<ComboBoxItem Content="PASS" Tag="PASS" IsSelected="True"/>
<ComboBoxItem Content="FAIL" Tag="FAILED" />
</ComboBox>
You can Use Triggers for the same (you should inherit the base style too)
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="Content" Value="PASS">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
I would suggest altering your style by creating style document separately in Window.Resources, and then styling your ComboBox items to have whatever foreground color you want.
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</ComboBox.Resources>
If you want to keep it in Application.Resources, then I think you need to track down what x:Static brush key is used for setting the TextBlock.Text color and overwrite that in your ComboBox.Resources

TextBox trigger to clear Text using a style

First, let me say I've been working with WPF for about a week. I want to style a TextBox so that when it is disable, it is cleared. This article explained how to do it, however I'm confused on how to set the generic style as a resource so that every TextBox can bind to a different property without repeating the style for each TextBox.
<Window.Resources>
<Style TargetType="{x:Type TextBox}" x:Key="style1">
<Setter Property="Text" Value="{What do I really put here?}" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
....
<TextBox Style="{StaticResource style1}" Text="{Binding SomeProperty}"/>
Thanks!
You won't be able to use the Text property like that. Setting the Text property explicitly on any TextBox that has that style will override the Text setter in the trigger (like you noticed).
If you only need the TextBox to be cleared and not the property it is binding to, then a workaround is to use an attached property (or Tag) for the text which you bind Text to in the Style.
Example..
<Style TargetType="{x:Type TextBox}" x:Key="style1">
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Self},
Path=Tag}"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
Then a TextBox can use this Style like
<TextBox Style="{StaticResource style1}" Tag="{Binding SomeProperty}" />

Style label host image and text

this is a two part question that probbably have a similar answer.
I want to create in a resource dictionary a style for a label that contains first an image and then the text. The text, as a TextBlock has it's own style (had no problems there). Here is what I have
Label Style:
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<TextBlock Style="{StaticResource TextBlockStyle}">
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TextBlockStyle:
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="25 0 0 2.5"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextDecorations" Value="Underline"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
Now my problem is when I add a new label to my Control (ex: Window) and specify the text (ex: Create), no text is shown.Something like:
<Label Style="{StaticResource LabelStyle}">Create</Label>
The text Create does not show, however if I put in my LabelStyle->TextBlock->text it shows, but it's no good since I want to change it for different labels. Is there a way to bind my Label text to my (Inside Style) TextBlock.Text???
My other question is the same, but for images, and Image.Source.
Thanks :-)
EDIT:
This is what I have now with H.B. answer implemented
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Grid>
<StackPanel Orientation="Horizontal">
<Image Source="/Resources/Create.png" />
<TextBlock Style="{StaticResource TextBlockStyle}" Text="{TemplateBinding Content}"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note that this is in the Resource Dictionary. For the TextBlock it works great. But for the image it's a different story. I want the same as the 'Text="{TemplateBinding Content}' but for the Image.Source and set it's path in my control when I add the label. Probabbly since it's multiple content I'll have to write more code than I'd like, but I'll settle for the easiest, cleanest answer.
H.B. thanks again and as for the hyperlink, this is still in development, it's not going to be in anyway a hyperlink, just some custom menu button with some animation so it's not so boring for the user :P
Your Label.Template no longer links the Content property of the Label (which you set to "Create") to any internal part. To fix this you can for example bind the TextBlock.Text like this:
<ControlTemplate TargetType="Label">
<TextBlock Style="{StaticResource TextBlockStyle}"
Text="{TemplateBinding Content}"/>
</ControlTemplate>
(I just noticed that you make the Label look like a hyperlink, you do realize that there already is a class for that, right?)

WPF Combobox Validation.ErrorTemplate error

I have a combobox that i need to edit its error template to show a red border when there is a validation error.
I am using the following style
<Style TargetType="{x:Type ComboBox}" >
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Border BorderBrush="Red" BorderThickness="3">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
The border never shows up when validation errors occur. Any tips what is going wrong?
The Style you posted works. You should check your binding, did you add ValidatesOnDataErrors=True and ValidatesOnExceptions=True to the binding of SelectedValue?
enter code heretry without the dock panel, that is uneuseful since it wraps jus one element. However, sicnecerely I don't wnow if it makes sense to wrap a textbox with a border, since it has already a border! You should try to change directly the colour of its border. You could try to use again the panel but then put the border around the panel ie:
Border BorderBrush="Red" BorderThickness="3"
DockPanel
AdornedElement
This makes more sense because the wrap panel has not its own border.
Use This.
<Style x:Key="textBoxStyle" TargetType="{x:Type telerik:RadMaskedTextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Control.BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
I don't like any of the responses here. Simply put, how do you change the border color for the error template for a ComboBox using Blend or not? It shouldn't be acceptable to draw another border around the existing border of the ComboBox. I've figured out how to creat a ControlTemplate in Blend but not a Validation Template.
I've come close with trying to make it appear like I've changed the actual border color, but that's not what I actually want. Suggestions? To complicate it a bit, I'd like to display a red asterisk outside of the right border of the control.
The following code is a close attempt, but it is actually drawing a border inside the ComboBox and if you look close, you can see that the border is 2 pixels wide when combined with the ComboBox border:
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder>
<Border BorderBrush="Blue" BorderThickness="1" CornerRadius="2" />
</AdornedElementPlaceholder>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
I searched around some more and came up with a solution based on another article here: WPF - How to apply style to AdornedElementPlaceholder's AdornedElement?
<!-- This works -->
<ComboBox Name="comboBox1" Style="{StaticResource NewComboBoxStyle}" Validation.ErrorTemplate="{StaticResource comboBoxValidationTemplate}" />
<SolidColorBrush x:Key="MainBorderBrush">#FF91B3FF</SolidColorBrush>
<Style x:Key="NewComboBoxStyle" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource myErrorTemplate}">
<Setter Property="BorderBrush" Value="{DynamicResource MainBorderBrush}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
<!-- Sets ToolTip when Validation.HasError is True. -->
<Style TargetType="Control" x:Key="myErrorTemplate">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="comboBoxValidationTemplate">
<DockPanel Name="myDockPanel">
<AdornedElementPlaceholder/>
<TextBlock Text="*" FontWeight="Bold" FontSize="14" Foreground="Red" DockPanel.Dock="Left" ToolTip="{Binding .CurrentItem}" />
</DockPanel>
</ControlTemplate>

Use a property trigger to change a property that already has a binding

How can I use a property trigger in a style (or another method) to change a property (ToolTip for example) that already has its value defined by a binding?
I have a simple button like so:
<Button Name="Button1" Style="{StaticResource ButtonStyle}"
ToolTip="{Binding Name}" >My Button</Button>
It has a binding on the tooltip to show the Name property of the class set as DataContext.
My problem is I want to show the Name when the button is enabled, but something else when it is disabled. I thought I could get around my problem with a style and a trigger like so:
<Style TargetType="Button" x:Key="ButtonStyle">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="ToolTip" Value="Disabled" />
</Trigger>
</Style.Triggers>
</Style>
But this doesn't work. If I removed the tooltip binding from the button then I do get the correct tooltip when the button is disabled. But it seems I can't have both a binding and a trigger on the same property.
I could get around it by adding another trigger like so:
<Trigger Property="IsEnabled" Value="true">
<Setter Property="ToolTip" Value="{Binding Name}" />
</Trigger>
But I would like to use the style for 4 or 5 buttons that will all have different bindings for the enabled ToolTip, but the same (fixed) tooltip when they are disabled.
Any suggestions?
The easiest solution to your problem is to create a button style that all of your buttons can use (_DisabledButtonToolTipStyle in the example below) and then define a unique style for each button that applies the enabled tool tip value. If the individual buttons always have a different tool tip value then I'd recommended simply embedding the style like below; however, if you wanted to reuse the enabled tool tip style you could easily define it in your resources and give it a key.
<Window.Resources>
<Style x:Key="_DisabledButtonToolTipStyle" TargetType="Button">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="ToolTip" Value="Disabled" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Name="Button1" Content="My Button">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource _DisabledButtonToolTipStyle}">
<Setter Property="ToolTip" Value="{Binding Name}" />
</Style>
</Button.Style>
</Button>
</Grid>
Your problem has nothing to do with binding, the problem is that properties you set directly on the element override the properties set in a style, for example:
Given the style
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
</Style>
And those two buttons:
<Button Content="1st"/>
<Button Content="2nd" Background="Red"/>
The first button will get its background from the style but the second overrides the style background.
You can get what you want with triggers but not using styles, you can use a DataTemplate like this (the TextBox and CheckBox are there for testing):
<ContentPresenter Content="{Binding}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<StackPanel>
<TextBox Name="edt" Text="Tooltip text"/>
<Button Name="btn" Content="x"
ToolTip="{Binding ElementName=edt, Path=Text}"
ToolTipService.ShowOnDisabled="True"/>
<CheckBox Content="Enabled"
IsChecked="{Binding ElementName=btn, Path=IsEnabled}"/>
</StackPanel>
<DataTemplate.Triggers>
<Trigger SourceName="btn" Property="IsEnabled" Value="False">
<Setter TargetName="btn" Property="ToolTip" Value="Disabled"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>

Resources