Styling WPF Applications and ViewModels
No edit summary
Line 1: Line 1:
This post is about how to get the cool things of WPF to merge with the cool things of ECO.We need to get the XAML styles into our declarative application
This post is about how to get the cool things of WPF to merge with the cool things of ECO. We need to get the XAML styles into our declarative application.


We need to declare and use style names on specific places in our UI where it makes sense to us. We need to inject FormatStrings into our declarative DataBindings.
We need to declare and use style names on specific places in our UI where it makes sense to us. We need to inject FormatStrings into our declarative DataBindings.


We need all of this at a granular level so that we will not be limited by the tool; for example we need to be able to control a single column in a grid separately, and also control its header differently than its cells.
We need all of this at a granular level so that we will not be limited by the tool. For example, we need to be able to control a single column in a grid separately as well as its header differently from its cells.


All of this is done with XAML ResourceDictionaries. You can do your own with blend or notepad or any tool you like.
All of this is done with XAML ResourceDictionaries. You make your own with Blend or Notepad or any tool you like.


If you add your dictionaries to the Config folder of ECO, we will pick them up in the style Menu:
If you add your dictionaries to the Config folder of ECO, we will pick them up in the style Menu:
Line 13: Line 13:
[[File:Styling WECPOF applications and ViewModels 2.png|frameless|260x260px]]
[[File:Styling WECPOF applications and ViewModels 2.png|frameless|260x260px]]


When you click a Style in WECPOF-runtime we load that Dictionary and merge it with the Application.
When you click a Style in WECPOF-runtime, we load that Dictionary and merge it with the Application.


=== What can you change? ===
=== What Can You Change? ===
[[File:Styling WECPOF applications and ViewModels 3.png|frameless|349x349px]]
[[File:Styling WECPOF applications and ViewModels 3.png|frameless|349x349px]]


Line 62: Line 62:
  </Style>
  </Style>


=== What can you do more? ===
=== What More Can You Do? ===
When you set the StyleRef on ViewModelColumns you can define a corresponding Style in XAML.
When you set the StyleRef on ViewModelColumns, you can define a corresponding Style in XAML.


[[File:Styling WECPOF applications and ViewModels 4.png|frameless|428x428px]]
[[File:Styling WECPOF applications and ViewModels 4.png|frameless|428x428px]]


Since the ViewModelColumn often spawns two controls; the TextBlock and in this case a TextBox we have defined the naming convention of STYLENAME.COMPONENTTYPE.
Since the ViewModelColumn often spawns two controls, the TextBlock and in this case, a TextBox, we have defined the naming convention of STYLENAME.COMPONENTTYPE.


This enables you to define Style1 for all control types you use:
This enables you to define Style1 for all control types you use:
Line 81: Line 81:
  </Style>
  </Style>


=== There is more ===
=== There is More ===
In WPF you can set a StringFormat on a Binding to aid in common transformations like “show only 2 decimals”, “present the DateTime in text format”, “This value is really percent” etc.
In WPF, you can set a StringFormat on a Binding to aid in common transformations like “show only 2 decimals”, “present the DateTime in text format”, “This value is really percent” etc.


This need too is addressed with a naming convention in the XAML resource dictionary:
This need is also addressed with a naming convention in the XAML resource dictionary:
  Code Snippet
  Code Snippet
  <!– Format string can be defined per Style and is used in the Binding – use this to format dates and doubles etc –>
  <!– Format string can be defined per Style and is used in the Binding – use this to format dates and doubles etc –>
  <sys:String x:Key="StyleNumber2Dec.StringFormat">{0:n}</sys:String>
  <sys:String x:Key="StyleNumber2Dec.StringFormat">{0:n}</sys:String>
  <sys:String x:Key="FormatDate.StringFormat">ddd d MMM</sys:String>
  <sys:String x:Key="FormatDate.StringFormat">ddd d MMM</sys:String>
You use a StyleRef in the ViewModelColumn, and create a string entry in the resource dictionary with a key of STYLENAME.StringFormat. We apply this when setting up the Binding for the components in your view.
You use a StyleRef in the ViewModelColumn and create a string entry in the resource dictionary with a key of STYLENAME.StringFormat. We apply this when setting up the Binding for the components in your view.


=== And we need Grid precision too ===
=== And We Need Grid Precision Too ===
A DataGrid has Styles that apply to the whole Grid, but also you can apply individual styles per GridColumn:
A DataGrid has Styles that not only apply to the whole Grid but also to individual styles per GridColumn:
  '''Code Snippet'''
  '''Code Snippet'''
   
   
Line 139: Line 139:
  </Style>
  </Style>


=== And the result ===
=== The Result ===
The result is that you can be very flexible in how you want to convey information:
The result is that you can be very flexible in how you want to convey information:


Line 148: Line 148:
[[File:Styling WECPOF applications and ViewModels 7.png|frameless|391x391px]]
[[File:Styling WECPOF applications and ViewModels 7.png|frameless|391x391px]]


=== Help us out please! ===
=== Help Us Out, Please! ===
Create your own styles and send them to us. We will use your name on the style so you will be a famous XAML designer before you know it!
Create your own styles and send them to us. We will use your name on the style so that you become a famous XAML designer before you know it!


=== Updates 2018 ===
=== Updates 2018 ===
To get generic styles to match all un-styled DateTime's for example you can now add this string format:
To get generic styles to match all un-styled DateTimes, for example, you can now add this string format:
     <sys:String x:Key="<u>DateTime</u>.StringFormat">yyyy-MM-dd HH:mm</sys:String>  
     <sys:String x:Key="<u>DateTime</u>.StringFormat">yyyy-MM-dd HH:mm</sys:String>  
This can be used for all simple types; double, float, bool etc - but not for string since that would not really help any.
This can be used for all simple types; double, float, bool, etc - but not for string since that would not be helpful.


[[Category:WECPOF]]
[[Category:WECPOF]]
[[Category:View Model]]
[[Category:View Model]]
[[Category:MDriven Designer]]
[[Category:MDriven Designer]]

Revision as of 09:31, 3 February 2023

This post is about how to get the cool things of WPF to merge with the cool things of ECO. We need to get the XAML styles into our declarative application.

We need to declare and use style names on specific places in our UI where it makes sense to us. We need to inject FormatStrings into our declarative DataBindings.

We need all of this at a granular level so that we will not be limited by the tool. For example, we need to be able to control a single column in a grid separately as well as its header differently from its cells.

All of this is done with XAML ResourceDictionaries. You make your own with Blend or Notepad or any tool you like.

If you add your dictionaries to the Config folder of ECO, we will pick them up in the style Menu:

Styling WECPOF applications and ViewModels 1.png

Styling WECPOF applications and ViewModels 2.png

When you click a Style in WECPOF-runtime, we load that Dictionary and merge it with the Application.

What Can You Change?

Styling WECPOF applications and ViewModels 3.png

Code Snippet

<!– WECPOFWinBackgroundBrush The background of a single window –> 
<LinearGradientBrush x:Key="WECPOFWinBackgroundBrush" EndPoint="0,1"StartPoint="0,0">
     <GradientStop Color="#eae" Offset="0.0" />
     <GradientStop Color="#777" Offset="1.0" /> 
</LinearGradientBrush>


<!– WECPOFWinContentBackgroundBrush The background of content plate of a single window –> 
<LinearGradientBrush x:Key="WECPOFWinContentBackgroundBrush" EndPoint="0,1"StartPoint="0,0">
     <GradientStop Color="#aea" Offset="0.0" />
     <GradientStop Color="#777" Offset="1.0" />
</LinearGradientBrush>


<!– WECPOFWindowEnvironmentBackgroundBrush The background of the containing window , the master window –>
<SolidColorBrush x:Key="WECPOFWindowEnvironmentBackgroundBrush"  Color="Coral">
</SolidColorBrush>

<!–   WECPOFWinFrameBrush  –>
   WECPOFWINHeaderStyle  The style used for the window header–>
<Style x:Key="WECPOFWINHeaderStyle" TargetType="{x:Type TextBlock}">
   <Setter Property="Foreground" Value="Snow"></Setter>
   <Setter Property="Margin" Value="2,0,2,0"></Setter>
   <Setter Property="FontSize" Value="20"/>
   <Setter Property="FontWeight" Value="ExtraBold"></Setter>
</Style>


<!–  WECPOFMenuStyle  The style used for Main Menu–>
<Style x:Key="WECPOFMenuStyle" TargetType="{x:Type Menu}">
     <Setter Property="Background" Value="{StaticResource MenuBackground}"/>
…CUT FOR CLARITY
     </Setter>
</Style>


<!–  WECPOFMenuItemStyle  The style used for MenuItems–>
<Style x:Key="WECPOFMenuItemStyle" TargetType="{x:Type MenuItem}">
     <Setter Property="Background" Value="Black"></Setter>
     <Setter Property="Foreground" Value="White"></Setter>
</Style>

What More Can You Do?

When you set the StyleRef on ViewModelColumns, you can define a corresponding Style in XAML.

Styling WECPOF applications and ViewModels 4.png

Since the ViewModelColumn often spawns two controls, the TextBlock and in this case, a TextBox, we have defined the naming convention of STYLENAME.COMPONENTTYPE.

This enables you to define Style1 for all control types you use:

Code Snippet 
<!– Style for the TextBlock part of a ViewModelCOlumn that has Style1 in the StyleRef–>
<Style x:Key="Style1.TextBlock" >
  <Setter Property="TextBlock.FontSize" Value="36"/>
</Style>

<!– Style for the TextBox part of a ViewModelCOlumn that has Style1 in the StyleRef–>
<Style x:Key="Style1.TextBox"  TargetType="{x:Type TextBox}">
    <Setter Property="FontSize" Value="36"/>
</Style>

There is More

In WPF, you can set a StringFormat on a Binding to aid in common transformations like “show only 2 decimals”, “present the DateTime in text format”, “This value is really percent” etc.

This need is also addressed with a naming convention in the XAML resource dictionary:

Code Snippet
<!– Format string can be defined per Style and is used in the Binding – use this to format dates and doubles etc –>
<sys:String x:Key="StyleNumber2Dec.StringFormat">{0:n}</sys:String>
<sys:String x:Key="FormatDate.StringFormat">ddd d MMM</sys:String>

You use a StyleRef in the ViewModelColumn and create a string entry in the resource dictionary with a key of STYLENAME.StringFormat. We apply this when setting up the Binding for the components in your view.

And We Need Grid Precision Too

A DataGrid has Styles that not only apply to the whole Grid but also to individual styles per GridColumn:

Code Snippet

<!– DataGrid column offers two styles, HeaderStyle and CellStyle –>
<!– This is how you define the HeaderStyle–>
<Style x:Key="StyleOnColumn.HeaderStyle.DataGridTextColumn" TargetType="{x:Type prim:DataGridColumnHeader}">
     <Setter Property="Height" Value="30"/>
     <Setter Property="Background" Value="Green"/>
     <Setter Property="Foreground" Value="Black"/>
     <Setter Property="FontSize" Value="28" />
</Style>


<!– DataGrid column offers two styles, HeaderStyle and CellStyle –>
<!– This is how you define the CellStyle–>
<Style x:Key="StyleOnColumn.CellStyle.DataGridTextColumn" TargetType="{x:Type tk:DataGridCell}">
     <Setter Property="Height" Value="30"/>
     <Setter Property="Background" Value="Yellow"/>
     <Setter Property="Foreground" Value="Black"/>
     <Setter Property="FontSize" Value="18" />
</Style>

<!– To tell a grid to use a default style on all ColumnHeaders–>
<Style x:Key="StyleOnColumn.ColumnHeaderStyle.DataGrid" TargetType="{x:Type tkPrimitives:DataGridColumnHeader}">
      <Setter Property="Height" Value="20"/>
      <Setter Property="Background" Value="Yellow"/> 
      <Setter Property="Foreground" Value="Green"/>
      <Setter Property="FontSize" Value="16" />
</Style>


<!– To tell a grid to use a RowStyle –>
<Style x:Key="StyleOnColumn.RowStyle.DataGrid" TargetType="{x:Type tk:DataGridRow}">
    <Setter Property="Height" Value="20"/>
    <Setter Property="Foreground" Value="Green"/>
    <Setter Property="FontSize" Value="16" />
</Style>


<!– To tell a grid to use a Default CellStyle –>
<Style x:Key="StyleOnColumn.CellStyle.DataGrid" TargetType="{x:Type tk:DataGridCell}">
    <Setter Property="Height" Value="20"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="Blue"/>
    <Setter Property="FontSize" Value="12" />
</Style>

The Result

The result is that you can be very flexible in how you want to convey information:

Styling WECPOF applications and ViewModels 5.png

Styling WECPOF applications and ViewModels 6.png

Styling WECPOF applications and ViewModels 7.png

Help Us Out, Please!

Create your own styles and send them to us. We will use your name on the style so that you become a famous XAML designer before you know it!

Updates 2018

To get generic styles to match all un-styled DateTimes, for example, you can now add this string format:

    <sys:String x:Key="DateTime.StringFormat">yyyy-MM-dd HH:mm</sys:String> 

This can be used for all simple types; double, float, bool, etc - but not for string since that would not be helpful.

This page was edited 52 days ago on 03/26/2024. What links here