TextBox Text Formatting From Style - wpf

I have a MainWindow.XAML
TextBox is added to it
TextBox text binding is done
When I add StringFormat inside binding (in MainWindow.XAML) it works
When I add StringFormat inside Style, it's not working
below is the code from style and MainWindow.xaml
<TextBox Grid.Row="1" Grid.Column="4" Style="{StaticResource TextBoxStyle}" Text="{Binding CustomerAmount,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" HorizontalAlignment="Stretch" Margin="10,0,0,0"/>
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}" >
<Setter Property="Text" Value="{Binding Text, RelativeSource={RelativeSource Self},StringFormat='#,###,###,##0.00;(#,###,###,##0.00)'}"></Setter>
</Style>

Well you've basically applied two Text binding's now, one in MainWindow and one in Style.
The Text property set in MainWindow.xaml on the control has precedence over the one you're setting in Style, so the StringFormat you set via Style is actually never applied cos that entire Style.Setter is ignored.
A very rough way to make this work and prove the above statement is try switching your xaml to the following,
<TextBox Grid.Row="1" Grid.Column="4" Style="{StaticResource TextBoxStyle}" Tag="{Binding CustomerAmount,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" HorizontalAlignment="Stretch" Margin="10,0,0,0"/>
and Style:
<Style x:Key="TextBoxStyle"
TargetType="{x:Type TextBox}">
<Setter Property="Text"
Value="{Binding Tag,
RelativeSource={RelativeSource Self},
StringFormat='#,###,###,##0.00;(#,###,###,##0.00)',
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</Style>
This will work cos you now have Tag binding in MainWindow and Text in Style. You can switch to a custom Attached property or DP to get the same behavior

Related

WPF TextBox BorderBrush Style vs. No Style

Why does a border appear around a TextBox when a Style is used as opposed to no Style being used? Is there a way to set this using a Style so no border appears, like in the "Phone" Grid/TextBox? See below:
WINDOW XAML
<!-- City, State, Zip -->
<Grid Grid.Column="0" Grid.Row="2" Background="White" Margin="50,2,25,2">
<Viewbox>
<TextBox Style="{Binding StandardTextBox1}" Text="{Binding CityStateZip}"/>
</Viewbox>
</Grid>
<!-- Phone -->
<Grid Grid.Column="0" Grid.Row="3" Background="White" Margin="50,2,25,2">
<Viewbox>
<TextBox
Background="Transparent"
BorderBrush="Transparent"
Text="{Binding FacilityPhoneMain}"
TextAlignment="Center"
FontSize="14"
/>
</Viewbox>
</Grid>
STYLE XAML
<!-- Standard TextBox 1 -->
<Style TargetType="TextBox" x:Key="StandardTextBox1">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="FontSize" Value="14"/>
</Style>
You can modify the BorderThickness property of the TextBox in your Style to remove the border.
As for why the border is not affected in the Style, I have a hunch that this is due to dependency property precedence.
Animations have a higher precedence than property setters. Due to the default WPF Textbox template having animations that affect the BorderBrush property, the setters are not being applied.
This link has some relevant information
To quote: "Animation values always take precedence over local values, setters and triggers"

DataTrigger in Style in HierarchicalDataTemplate not working -- TreeView

I have a DataTrigger to set a TextBox's Background based on a bound property.
Here's a streamlined version of the xaml:
<TreeView >
<TreeViewItem Header="Things" >
<TreeViewItem.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="True">
<Setter Property="Background" Value="LightGray" />
</DataTrigger>
</Style.Triggers>
</Style>
<HierarchicalDataTemplate DataType="{x:Type local:Type1}" ItemsSource="{Binding Children, Mode=OneWay}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="6,0,6,0" />
<TextBlock Text="{Binding IsDirty}" Margin="6,0,6,0" />
<i:Interaction.Behaviors>
<dragDrop:FrameworkElementDropBehavior DragEffect="Move" />
</i:Interaction.Behaviors>
</StackPanel>
</HierarchicalDataTemplate>
</TreeViewItem.Resources>
</TreeViewItem>
I added a TextBlock to display the value of the IsDirty property; when that is true, the Background remains unchanged.
I have tried moving the Style to the HierarchicalDataTemplate.Resources, but that made no difference.
What am I overlooking?
Thanks --
That's because implicit styles targeting types not derived from Control do not cross the template boundary, i.e. are not applied inside templates unless they're defined within that template's scope. Here's a good post explaining how it works and why does it work this way.
In order to cross the template boundary, you should use a type deriving from Control (e.g. a Label) instead of a TextBlock and define implicit style targeting that type.
Otherwise, you could put your style in scope of the template in question by moving it into the template's resources dictionary:
<HierarchicalDataTemplate (...)>
<HierarchicalDataTemplate.Resources>
<Style TargetType="{x:Type TextBlock}">
(...)
</Style>
</HierarchicalDataTemplate.Resources>
(...)
</HierarchicalDataTemplate>

Style of a TextBox: Why is 'AcceptsReturn=true' not applied?

I have a custom control in WPF, which consists of a toggle button, a TextBlock and a TextBox. What I basically want to do is to show the TextBox when the toggle button is checked and the TextBlock otherwise. Furthermore I want allow defining to style properties on the control via dependency properties, which are applied to the TextBlock and the TextBox at runtime. The default template looks like this:
<Style TargetType="{x:Type views:EditableLabel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type views:EditableLabel}">
<Border Background="{TemplateBinding Background}">
<DockPanel Margin="0">
<telerik:RadToggleButton x:Name="PART_Toggle"
DockPanel.Dock="Right"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsInEditMode, Mode=TwoWay}">
<Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ToggleImage}" Height="14" />
</telerik:RadToggleButton>
<TextBlock x:Name="PART_TextBlock"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}" >
</TextBlock>
<TextBox x:Name="PART_TextBox"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The custom control has two dependency properties for styles, one for the PART_TextBlock and one for PART_TextBox. The styles are assigned in the OnApplyTemplate method of the custom control and in the property change callbacks of the two dependency properties:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_textBlock = (TextBlock) GetTemplateChild("PART_TextBlock");
_textBox = (TextBox) GetTemplateChild("PART_TextBox");
_toggleButton = (RadToggleButton) GetTemplateChild("PART_Toggle");
ApplyStyles();
UpdateVisibilities();
}
private void ApplyStyles()
{
if (_textBlock != null) _textBlock.Style = TextBlockStyle;
if (_textBox != null) _textBox.Style = TextBoxStyle;
}
(The callbacks are not shown here, as they are trivial, just calling ApplyStyles().
I use the custom control like this:
<views:EditableLabel Text="{Binding SelectedToolbox.Description, Mode=TwoWay}"
CanEdit="{Binding SelectedToolbox.CanEdit}"
ToggleImage="../Resources/Images/edit-26.png">
<views:EditableLabel.TextBlockStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</views:EditableLabel.TextBlockStyle>
<views:EditableLabel.TextBoxStyle>
<Style TargetType="TextBox">
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="AcceptsReturn" Value="True" />
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
</Style>
</views:EditableLabel.TextBoxStyle>
</views:EditableLabel>
Everything works as expected, except from the AcceptsReturn setter is not applied, which I find very strange. I've debugged ApplyStyles(): The style is assigned correctly and both setters are contained within the style.
TextWrapping and VerticalScrollBarVisibility are both set correctly:
while AcceptsReturn is not:
Any ideas, what might be the issue here?
The screenshot you posted suggests AcceptsReturn has a local value, i.e., a value set by explicitly calling the property setter or SetValue. Do you have any code in EditableLabel which explicitly sets the AcceptsReturn property? If so, the local value you set will take precedence over any style setters. You can avoid this by using SetCurrentValue to change the value while leaving the value source unchanged.
Secondly, rather assigning the style in your code behind, it is generally easier and more reliable to simply bind the style within the template, e.g.:
<TextBox x:Name="PART_TextBox" Style="{TemplateBinding TextBoxStyle}" ... />
You might try this first and see if you get better results.

WPF: Simple MSWord-like color picker button

Is there a quick and easy way to implement a color picker button like the one in MS Word?
I want the user to choose from a number of predefined colors in a dropdown. The selected color should be displayed when the button is closed. When the user clicks the button, an event or command should be triggered. I want to use one button instance to set the text color in a RichTextBox, and another one to set the background color (similar to MS Word).
My first approach was to use a ComboBox with a DataTemplate which contains a button.
This does not work: The button's command is not triggered when the user clicks it. Instead, the dropdown of the ComboBox opens. I don't know the exact reason, but maybe the IsHitTestVisible=false attributes in the ComboBox default template? See: http://msdn.microsoft.com/en-us/library/dd334408%28v=vs.95%29.aspx
<UserControl x:Class="MyBrushPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Height="Auto" Width="Auto" MinWidth="50">
<UserControl.Resources>
<!--
Provide two different DataTemplates:
- SelectionBoxTemplate is used to display the selected color when the ComboBox is closed.
It contains a button which should be clickable (does not work).
- NormalItemTemplate is used to display a color in the opened ComboBox popup.
See:
http://stackoverflow.com/questions/2214696/wpf-how-to-customize-selectionboxitem-in-combobox
-->
<DataTemplate x:Key="NormalItemTemplate">
<Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate">
<!-- This button cannot be clicked: PreviewMouseDown and Button_Click events are never triggered. -->
<Button Click="Button_Click" PreviewMouseDown="Button_PreviewMouseDown">
<Border Height="44" Width="44" Margin="3,3,3,3" BorderThickness="1" BorderBrush="Black" Background="{Binding Mode=OneWay}"/>
</Button>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</UserControl.Resources>
<ComboBox IsReadOnly="True" IsEditable="False"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectableBrushes, Mode=OneWay}"
SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedBrush, Mode=TwoWay}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
MinHeight="50"
MaxDropDownHeight="200"
ItemTemplate="{StaticResource CombinedTemplate}"
>
<ComboBox.Resources>
<Style TargetType="ComboBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" Width="200" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ComboBoxItem">
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
</Style>
</ComboBox.Resources>
</ComboBox>
</UserControl>
Is there a way to make the button work correctly?
Are there any better approaches?
EDIT: Using the Snoop tool revealed that the IsHitTestVisible attribute of the unnamed ContentPresenter inside the ComboBox is actually set to false (ValueSource: ParentTemplate). If I set this property to true using Snoop, the button becomes clickable.
Can I change this property from a style?
At least, the following doesn't work:
<ComboBox.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="IsHitTestVisible" Value="True" />
</Style>
</ComboBox.Resources>
Assuming you are not just doing this as a learning exercise (which make using a library pointless)...
Take a look at: Extended WPF Toolkit - Color Picker
I've used it before for simple a plug-and-play WPF color-picker and it should solve your problem nicely.

remove red rectangle around combobox

i need to remove red rectangle around combobox. I have setup combobox in xaml like (below) this and i`m trying to override of the Validation.ErrorTemplate.
<ComboBox x:Name="comboPodkategoria"
Margin="0,3,0,0"
IsSynchronizedWithCurrentItem="False"
IsEditable="False"
ItemsSource="{Binding Source={StaticResource PodKategoriaLookup}, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
SelectedValue="{Binding IDPodKategoria}"
DisplayMemberPath="kat_popis" SelectedValuePath="IDPodkat" TabIndex="5" Style="{StaticResource combostyle}">
<Validation.ErrorTemplate>
<ControlTemplate>
</ControlTemplate>
</Validation.ErrorTemplate>
</ComboBox>
And style for removing red rectangle, but a have some error in xaml saying that Visibility property is not recognized or is not accessible. Style definition is below.
<Style x:Key="combostyle">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Visibility" TargetName="NotValid" Value="Visible"/>
</Trigger>
</Style.Triggers>
Any idea? :(
Use this to modify the Validation.ErrorTemplate
<ControlTemplate x:Key="ComboBoxValidationErrorTemplate">
<DockPanel>
<Border BorderBrush="Blue" BorderThickness="4">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
And then use it in your ComboBox like
<ComboBox Validation.ErrorTemplate="{StaticResource ComboBoxValidationErrorTemplate}"
...>
To have no indication of a Validation Error, remove the DockPanel, set Visibility to Collapsed or any other way you like.
Almost forgot, probably the easiest way to remove the "Red Border"
<ComboBox Validation.ErrorTemplate="{x:Null}"
...>
Add your Combobox, Validation.ErrorTemplate="{x:Null}" ; this code is ignore errors.
The setter in your trigger is setting the Visibility property of an element named "NotValid". That is not defined in the XAML you posted. If there is no element named "NotValid", that is your problem.

Resources