WPF Component Styles - c#

I'm just starting studying WPF and a have this project to do.
I wrote this at the App Resources (app.xaml), don't know if this is the right thing to do to set the design of the components, but I thought it was pratical.
But when I started the program this happened thats the program running
Do I have how to fix this, or I have to declarate the styles on the XAML os the screen?
Thanks a Lot!
Sorry about the English if there is any type mistakes
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="Width" Value="210" />
<Setter Property="Height" Value="30" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="15" />
<Setter Property="TextWrapping" Value="NoWrap" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="PasswordBox">
<Setter Property="Width" Value="210" />
<Setter Property="Height" Value="30" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="15" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="15" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="Button">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="30" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="DataGrid">
<Setter Property="Width" Value="600" />
<Setter Property="Height" Value="400" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontSize" Value="15" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style TargetType="Image">
<Setter Property="IsHitTestVisible" Value="True" />
</Style>
</Application.Resources>

Looking at your screenshot, Chris W called it with his comment advising you to look at the overall layout of your page first. Unfortunately, I cannot see what you have the height and width for the page itself set at, but it looks like the default is much smaller than the screen.
So, first - let's address the overall layout of the page before looking at any of the styling. I'm going to use a Grid and some StackPanels (I am typing straight into this answer, but hopefully I am going to be close. Consider this the disclaimer lol)
<Grid Style="{StaticResource LoginLayout}" x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<TextBlock Text="Login"/>
<TextBox x:Name="txtLogin"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Vertical">
<TextBlock Text="Senha"/>
<PasswordBox x:Name="txtPassw"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Button x:Name="btnLogin" />
<Button x:Name="btnExit" />
</StackPanel>
</Grid>
The Grid container, and the StackPanels handle the layout and positioning of the elements and will help start a bit more responsive layout (not perfect, but coding this on the fly so to speak right now).
As for the styles, you probably noticed the Grid having a style - it is my habit and I prefer it especially when I am dealing with much larger projects. So, lets take a swing at the styles...
<Style x:Key="LoginLayout" TargetType="{x:Type Grid}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Width" Value="110"/>
</Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
</Style>
The styles you already defined for the other items should work, but may need a bit of tweaking - here is the button one as an example:
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Margin" Value="3"/>
</Style>
I know this isn't a perfected style, however most of the positioning of these items are being handled by the grid and stackpanels. There are several other ways you could lay this page out - but hopefully this gets you started in the right direction.
Good luck!

Related

Calendardatepicker dateformat

Is it possible to set dateformat in Calendardatepicker style/template?
<Style x:Name="CalendarDatePicker" TargetType="CalendarDatePicker">
<Setter Property="Foreground" Value="Green" />
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="DateFormat" Value="{}{day.integer}‎.‎{month.integer}‎.{year.full}" />
</Style>
I tried to do it as above but it does not work.
I don't why CalendarDatePicker is designed in this way, DateFormat is only accepted if it's "ReadLocalValue" is true.
That mean the following two changes are valid:
<CalendarDatePicker x:Name="myCalendarDatePicker"
DateFormat = "{}{dayofweek.full}‎, ‎{month.full}‎ ‎{day.integer}‎, ‎{year.full}"/>
or
myCalendarDatePicker.DateFormat = "{dayofweek.full}‎, ‎{month.full}‎ ‎{day.integer}‎, ‎{year.full}";
So It doesn't work for your example. You can workaround the problem by creating a nested dummy CalendarDatePicker, but I don't suggest you to do it.
<Style x:Key="CalendarDatePicker" TargetType="CalendarDatePicker">
<Setter Property="Foreground" Value="Green" />
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="DateFormat" Value="{}{day.integer}‎.‎{month.integer}‎.{year.full}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CalendarDatePicker">
<Grid x:Name="RootElement">
<CalendarDatePicker DateFormat="{TemplateBinding DateFormat}"
Foreground="{TemplateBinding Foreground}"
Margin="{TemplateBinding Margin}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to do proper implicit styling of TextBox inside DataGrid (WPF, C#)

I have a WPF project, where i want to do implicit styling for all Windows of my program.
I am facing problems with the DataGridTextColumn in my DataGrid. This is a TextBlock in view mode and a TextBox in EditMode, but my styles to not apply to them.
My Implicit Styling
<System:Double x:Key="FontSize">14</System:Double>
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="Margin" Value="3" />
<Setter Property="MinWidth" Value="30" />
<Setter Property="Height" Value="20" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="White" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxStyle}" />
This styling is not applied to DataGridTextColumn in Edit mode.
I found some help in this StackOverflow Question
<Style TargetType="DataGridCell">
<Setter Property="TextElement.FontSize" Value="{StaticResource FontSize}" />
</Style>
The end result is that the FontSize is now applied, but the Content is Vertically Top Aligned
I then found a solution to Vertically CenterAlign the content of the DataGridTextColumn
<Style TargetType="DataGridCell">
<Setter Property="TextElement.FontSize" Value="{StaticResource FontSize}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Unfortunately, i now face Borders in my EditMode
I have tried various solutions to try and remove the Borders around the TextBox, but i have been unable.
Is there anyway where i can specify that my implicit TextBox style should also apply to the DataGridTextColumn Editmode?
I am finding WPF Styling to be limiting and hard to understand. I hope someone can provide some clarity
You could set the EditingElementStyle of all columns to your TextBoxStyle, e.g.:
<DataGrid ...>
<DataGrid.Resources>
<System:Double x:Key="FontSize">14</System:Double>
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="Margin" Value="3" />
<Setter Property="MinWidth" Value="30" />
<Setter Property="Height" Value="20" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="White" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Property1}" EditingElementStyle="{StaticResource TextBoxStyle}" />
<DataGridTextColumn Binding="{Binding Property2}" EditingElementStyle="{StaticResource TextBoxStyle}" />
</DataGrid.Columns>
</DataGrid>
There is no implicit styling for these TextBoxes so you need to set the EditingElementStyle property of each individual column I am afraid.

WPF Update Border Style BlockText trigger

Is it possible updating the parent border with triggers from the TextBox is Valid? I tried with Using a Data Template approach. I can not use it because I am trying to pass two properties in data context. One for placeholder and another to bind the User.Email.
If exists a better way to accomplish that achievement, I started using WPF.
I also tried using this approach. Created a ControlTemplate and use ScrollViewer x:Name="PART_ContentHost" but the styles don't update.
The point is how a can keep the binding and update the parent border in the more efficient way?
In View:
<Border Style="{DynamicResource TextBoxBorderStyle}" >
<Grid>
<TextBlock Text="{Binding Path=UserPlaceholder}"
Style="{StaticResource PlaceHolderTextStyle}">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource textInputToVisibilityConverter}">
<Binding ElementName="Email" Path="Text.IsEmpty" />
<Binding ElementName="Email" Path="IsFocused" />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<TextBox Name="Email"
Background="Transparent"
Style="{StaticResource textBoxBase}"
Text="{Binding Path=UserCredentials.Email,
Mode=TwoWay,
TargetNullValue='',
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}">
</TextBox>
</Grid>
</Border>
In App Border Style:
<Style x:Key="TextBoxBorderStyle"
TargetType="{x:Type Border}">
<Setter Property="BorderBrush"
Value="{DynamicResource TextBoxBorderBrush}"/>
<Setter Property="Background"
Value="{StaticResource TextBoxBackgroundBrush}"/>
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
<Setter Property="VerticalAlignment"
Value="Center"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="CornerRadius"
Value="{StaticResource DefaultBorder}"/>
<Setter Property="Height"
Value="50"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBox}}, Path=Validation.HasError}" Value="True">
<Setter Property="BorderBrush"
Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
In App Textblock Style:
<Style x:Key="textBoxBase" TargetType="{x:Type TextBox}">
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
<Setter Property="VerticalAlignment"
Value="Center"/>
<Setter Property="Foreground"
Value="{StaticResource TextBoxForegroundBrush}"/>
<Setter Property="FontSize"
Value="16"/>
<Setter Property="Margin"
Value="{StaticResource DefaultMargin}"/>
<Setter Property="FontFamily"
Value="{StaticResource DefaultFontFamily}"/>
<Setter Property="BorderThickness"
Value="0"/>
</Style>
To display some elements on error in a control you need to use Validation.ErrorTemplate attached property. You may find this post useful or look at the error template in the MahApps.Metro.

Calendar of DatePicker fills whole screen

I have a DatePicker in my application, that consists of DockPanels in a StackPanel in a ScrollViewer in a UserControl.
The (simplified) xaml of the UserControl looks like this:
<UserControl x:Class="project.UI1"
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"
xml:lang="de-DE"
mc:Ignorable="d" >
<UserControl.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Width" Value="250"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Padding" Value="3"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="MaxWidth" Value="{Binding RelativeSource={RelativeSource AncestorType=Border},Path=ActualWidth}"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
</Style>
<Style TargetType="{x:Type DatePicker}">
<Setter Property="Margin" Value="2"/>
<Setter Property="Width" Value="105"/>
<Setter Property="MaxWidth" Value="105"/>
<Setter Property="Height" Value="24"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="2"/>
</Style>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
</Style>
</UserControl.Resources>
<ScrollViewer>
<StackPanel>
<DockPanel>
<TextBlock Text="IK-Nummer des Absenders (z.B. D-Arzt)"/>
<Border>
<TextBox Text="{Binding p_1}"/>
</Border>
</DockPanel>
<DockPanel>
<TextBlock Text="IK-Nummer der UNI-DAV aus UV-Träger-Verzeichnis"/>
<Border>
<TextBox Text="{Binding p_2}" />
</Border>
</DockPanel>
<DockPanel>
<TextBlock Text="Datum der Erstellung durch den Leistungserbringer"/>
<DatePicker SelectedDate="{Binding p_3}"/>
</DockPanel>
</StackPanel>
</ScrollViewer>
</UserControl>
The TextBlocks have a 250px fixed width and hold the description of the fields while the TextBoxes for the user input are supposed to grow & shrink dynamically as the user resizes the window, to fit the rest of the window width.This is why I came up with packing every TextBlock/TextBox-combo in a DockPanel, and stack those in a StackPanel.
However, when I click on the DatePicker, the calendar beyond spans across the whole screen:
Even though this looks quite funky, I would prefer to get the common square calendar "popup" back.
Unfortunately, I don't know what causes the calendar to go wild like this at the moment...
The problem is your TextBlock style. It is being applied to the DateTimePicker because it has no key and so applies to all TextBlocks down the visual tree.
Can you give the style a key and only apply it to certain TextBlocks?
<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockStyle">
<Setter Property="Width" Value="250"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Padding" Value="3"/>
</Style>
....
<TextBlock Text="IK-Nummer der UNI-DAV aus UV-Träger-Verzeichnis"
Style="{StaticResource TextBlockStyle}"/>
UPDATE:
OR, you could just add a new TextBlock style to the DatePicker's resource to override the style higher up in the visual tree:
<DatePicker SelectedDate="{Binding p_3}">
<DatePicker.Resources>
<Style TargetType="{x:Type TextBlock}"/>
</DatePicker.Resources>
</DatePicker>

Nested Styles in WPF

I would like to nest Styles in WPF.
I have a resource dictionary:
<Style x:Key="BottomButtonBar" TargetType="{x:Type Grid}">
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
</Style>
What I want is: If I apply the style "BottomButtonBar" on a grid, Buttons which are inside this grid have Margin and Width I've defined and the same for the TextBlock inside this grid.
How to do that?
I finally found the following solution:
<Style x:Key="BottomButtonBar" TargetType="{x:Type Grid}">
<Style.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
</Style.Resources>
</Style>
And in the XAML:
<Grid DockPanel.Dock="Bottom" Style="{DynamicResource BottomButtonBar}">
If you want to add styles to elements in the Grid, you can make the styles implicit and add them to the resources of the Grid to limit their scope:
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
<Grid.Resources />
<Button ... />
</Grid>

Categories