DecimalUpDown decimal places - wpf

I have wpf view with xceed DecimalUpDown control.
<xctk:DecimalUpDown Grid.Row="5" Grid.Column="0" x:Name="Notional" Increment=".1" Style="{StaticResource DecimalUpDown}" Minimum="0" Validation.ErrorTemplate="{x:Null}" />
Style for this control.
<Style x:Key="DecimalUpDown" TargetType="xctk:DecimalUpDown" BasedOn="{StaticResource ErrorTemplate}">
<Setter Property="Height" Value="24" />
<Setter Property="Margin" Value="5,5,5,5" />
<Setter Property="FormatString" Value="F" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
How can I change the number of decimal places on view? On viewmodel is what I write to control, but after lost focus it changes to two decimal places.

Related

HOWTO override properties from a custom WPF UserControl

I have below WPF UserControl:
<UserControl x:Class="myComponents.UI.TextBoxWithPlaceholder"
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"
xmlns:local="clr-namespace:pEp.UI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Loaded="UserControl_Loaded">
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:TextBoxWithPlaceholder}}"
Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="myCustomTextBox"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
Padding="5"
IsReadOnly="{Binding IsReadOnly}"
HorizontalAlignment="Stretch"
TextChanged="CustomTextBox_TextChanged"
GotFocus="CustomTextBox_GotFocus"
LostFocus="CustomTextBox_LostFocus"
Margin="5"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
<TextBlock Name="myPlaceholderTextBlock"
IsHitTestVisible="False"
Padding="5"
Text="{Binding Placeholder}"
HorizontalAlignment="Left"
Foreground="DarkGray"
Margin="5">
</TextBlock>
</Grid>
</UserControl>
Basically it is a TextBox with a placeholder.
Now from a WPF view I reuse this component by doing:
xmlns:ui="clr-namespace:myComponents.UI"
and then place it as a normal control:
<ui:TextBoxWithPlaceholder Name="myNewTextBox" IsReadOnly="{Binding IsReadOnly}"
Style="{StaticResource myTextBoxStyle}"
Placeholder="please, enter something here"/>
Now as you see above I set a custom style for it:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
Now in my "myNewTextBox" control I am trying to override some inherited properties for the controls named myCustomTextBox and myPlaceholderTextBlock such as Margin, Padding, Background, Foreground, BorderBrush, etc. but I have tried above style and it is not working. Also I have tried:
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Setter Property="{Binding Path=Margin, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myCustomTextBox}" Value="0" />
<Setter Property="{Binding Path=Margin, ElementName=myPlaceholderTextBlock }" Value="0" />
<Setter Property="{Binding Path=Padding, ElementName=myPlaceholderTextBlock }" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="{Binding Path=Background, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=Foreground, ElementName=myCustomTextBox}" Value="{x:Null}"/>
<Setter Property="{Binding Path=BorderBrush, ElementName=myCustomTextBox}" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
If you want to be able to set properties of the myCustomTextBox from view that consumes your TextBoxWithPlaceholder control, you should add dependency properties to the latter and bind to them in TextBoxWithPlaceholder.xaml and set them in the consuming view, e.g.:
<ui:TextBoxWithPlaceholder ....PlaceHolderMargin="10" />
TextBoxWithPlaceholder.xaml:
<TextBlock Name="myPlaceholderTextBlock"
...
Margin="{Binding PlaceHolderMargin,RelativeSource={RelativeSource AncestorType=UserControl}}">
I am afraid you cannot refer to ElementName=myPlaceholderTextBlock from a namescope outside the TextBoxWithPlaceholder control so trying to do this in a Style that's defined in a consuming view won't work.
This is a task that cries out for a Custom control and Visual States instead of a UserControl with Triggers. But if you must do this as a UserControl (and I don't blame you because that's a lot to learn at this stage) then here goes:
First of all, when you use ElementName it is supposed to refer to elements that the XAML processor has already seen, previously in the current UI being laid out. Not elements inside the control being styled. I don't see that approach working.
If you want the TextBox and TextBlock inside a TextBoxWithPlaceholder to use the properties of that outer control, you could bind them to it, inside your control's XAML. For example, to rewrite a small part of that binding the background.
<TextBox Name="myCustomTextBox"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
Background={Binding RelativeSource={RelativeSource.FindAncestor, AncestorType={x:Type ui:TextBoxWithPlaceholder}, Path=Background}}"
But if you truly want that nested TextBox ("myCustomTextBox") to use a style with triggers and its own dedicated property values, then what you might try is creating a Resources section inside your style that itself contains implicit styles for the TextBox and TextBlock Something like this
<Style x:Key="myTextBoxStyle" TargetType="{x:Type ui:TextBoxWithPlaceholder}">
<Style.Resources>
<!-- Implicit style for TextBox should only apply to TextBoxes inside a TextBoxWithPlaceholder -->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Background Value="{x:Null}"/>
<Setter Property="Foreground" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
<Style.Triggers>
</Style>
</Style.Resources>
</Style>

how to create some simple styling for SelectedItem of a wpf combobox?

I have a very simple WPF combobox as under:
<ComboBox Width="192" Height="30" Style="{StaticResource StyleCombobox1}" />
and i have defined the style for this combobox in App.xaml as under:
<Style x:Key="StyleCombobox1">
<Setter Property="Control.FontFamily" Value="{Binding Source}" />
<Setter Property="Control.FontSize" Value="16" />
<Setter Property="Control.Background" Value="WhiteSmoke" />
<Setter Property="Control.Foreground" Value="Green" />
</Style>
How do i set some font styling,background etc for the currently SelectedItem being displayed in Combobox?

Can I apply a WPF style to an element only in a certain layout?

I have a TextBlock style like this:
<Style TargetType="TextBlock" x:Key="FormLabel">
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
I use it in Grid based forms, e.g:
<TextBlock Text="Code" Grid.Row="1" Grid.Column="0" Style="{StaticResource FormLabel}" />
Now instead of repeating the style name on every TextBlock in the grid, I would prefer to e.g. have a Grid style like:
<Style TargetType="Grid" x:Key="FormGrid">
<Setter Property="Width" Value="400" />
...
</Style>
Then I would, if possible, like to modify my TextBlock style to only apply to that element when it is a child element of a Grid with style FormGrid.
Is this possible, and if so, how can I achieve it?
This is indeed possible by using an implicit style within another style as a resource. Take this example:
...
<Window.Resources>
<Style x:Key="FormGrid" TargetType="Grid">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
<Setter Property="Width" Value="400" />
</Style>
</Window.Resources>
<StackPanel>
<Grid Style="{StaticResource FormGrid}">
<TextBlock Text="This text block is styled with FormGrid TextBlock implicit style."/>
</Grid>
<TextBlock Text="This text block uses the default style."/>
</StackPanel>
...
This is not possible by out of the box WPF abilities. What you are looking here is CSS like style selectors. WPF Only allows style inheritance through BasedOn property. I am not sure if this could be an alternative, but you can define that specific TextBlock style as part of that grid resources and target to match any textblock inside of it.
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Grid.Resources>

WPF: Button not taking the full space in a Listbox

I've a ListBox, in which I will have some Button added by prism.
For now, I've the following code(with some dummy button here just for testing purpose:
<DockPanel LastChildFill="True">
<ListBox HorizontalContentAlignment="Stretch" Padding="0" Margin="0" BorderBrush="Black" DockPanel.Dock="Left" HorizontalAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Resources>
<Style TargetType="Button">
<Setter Property="Height" Value="60" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</ListBox.Resources>
<Button>Button 1</Button>
<Button >Button 2</Button>
</ListBox>
<ContentControl></ContentControl>
</DockPanel>
The issue that I'm having currently is that my buttons are not taking the full space:
How to make sure it use all the available space?
Is there some way to ensure that all buttons will be have the height = to the width?
(just to be clear, I don't want anything set on the button since they will be provided by Prism from different modules)
When I run the application and focus an object, it seems we see that the ListBoxItemis taking the full place but the Button inside isn't:
How to make sure it use all the available space?
This is due to how the ListBox control's template is designed. To remove the small margin at the left and right of the button, set Padding=0 for the ListBoxItem style.
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
Is there some way to ensure that all buttons will be have the height = to the width?
You could do a RelativeSource binding to bind the container's height to the actual width of the parent ListBox:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource AncestorType=ListBox},Path=ActualWidth}" />
</Style>
</ListBox.ItemContainerStyle>

WPF Design-Time vs Run-Time Style Differences with Triggers

I am having a big issue with how XAML is rendered in Design-Time vs Run-Time. For the most part, things are consistent, but when I use any styles which have a Trigger, the trigger is not checked in Design-Time.
Here is a sample application to show how things are displayed differently:
<Window x:Class="DesignDifferencesWithDesignAndRuntime.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="400">
<Window.Resources>
<Style x:Key="multiLineInTrigger" TargetType="{x:Type TextBox}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="22" />
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="AcceptsReturn" Value="True">
<Setter Property="Width" Value="Auto" />
<Setter Property="Height" Value="Auto" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="singleLineInTrigger" TargetType="{x:Type TextBox}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Height" Value="Auto" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="AcceptsReturn" Value="False">
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="22" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Single (Single Style)" Grid.Row="0" Grid.Column="0" />
<TextBlock Text="Single (Multi Style)" Grid.Row="1" Grid.Column="0" />
<TextBlock Text="Multi (Single Style)" Grid.Row="2" Grid.Column="0" />
<TextBlock Text="Multi (Multi Style)" Grid.Row="3" Grid.Column="0" />
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource singleLineInTrigger}" />
<TextBox Grid.Row="1" Grid.Column="1" Style="{StaticResource multiLineInTrigger}" />
<TextBox Grid.Row="2" Grid.Column="1" Style="{StaticResource singleLineInTrigger}" AcceptsReturn="True" />
<TextBox Grid.Row="3" Grid.Column="1" Style="{StaticResource multiLineInTrigger}" AcceptsReturn="True" />
</Grid>
I created two separate TextBox styles which do the exact same thing. When the TextBox is Single-Line (AcceptsReturn = False) I need the width to be 150, and the height to be 22. When it is Multi-Line (AcceptsReturn = True, obviously) I need the width and height to stretch and take up the entire space.
Both of these triggers work perfectly in Run-Time, as running this code will show, but in Design-Time they both fail to work on the trigger condition. When using the "multiLineInTrigger" style, the textbox will have the height and width set statically (regardless of AcceptsReturn), but when using the "singleLineInTrigger" style, the controls will be stretched regardless of AcceptsReturn value.
Is there a solution for this issue? This has become quite troublesome and time-consuming for the development team because they do not know when it is working vs when it is not until compiling and running the application (which is a lengthy process).
Thanks.
I've seen this problem many times and I've never seen a workaround for it, Triggers doesn't work in Visual Studio 2010 Designer. Hopefully they can get this fixed soon.
The only solution I can think of is to do the design work in Expression Blend 4 instead where this works perfectly. Might not be ideal but at the moment I don't think you have any other choise

Resources