WPF style from HDD file - c#

In my application I'm using ResourceDictionaries for styles. Example:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}" x:Key="SimpleButton">
<Setter Property="Foreground" Value="{DynamicResource SpecialRed}"/>
<Setter Property="FontSize" Value="40"/>
<Setter Property="Margin" Value="10"/>
</Style>
</ResourceDictionary>
Lets say that as a user I know how resource dictionary look like. Is it possible to overwrite the resource from my own file from HDD? I want to add the functionality which allows user to do this.
My HDD file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}" x:Key="SimpleButton">
<Setter Property="Foreground" Value="{DynamicResource SpecialRed}"/>
<Setter Property="FontSize" Value="70"/>
<Setter Property="Margin" Value="20"/>
</Style>
</ResourceDictionary>

If you insist on doing that (I wouldn't), you can merge resource dictionaries at runtime: Dynamically loading resource dictionary files to a wpf application gives an error

Related

WPF - Styles declared in Resource Dictionary not getting applied

I have added the following styles in App.xml file of WPF application under Application.Resources tag and these styles are getting applied to the controls.
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontFamily" Value="Calibri" />
</Style>
<Style TargetType="{x:Type Control}" x:Key="fontStyling">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontFamily" Value="Calibri" />
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource fontStyling}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource fontStyling}" />
Now, i have created a "Resource Dictionary" file, moved the above styles to Resource dictionary file and accessed the "Resource Dictionary" file in the App.XAML file using merged dictionaries
<ResourceDictionary x:Key="GlobalSettingsDictionary">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionaries/GlobalSettings.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
When i run the WPF application then the Styles in the resource dictionary are not getting applied to the controls present in the Main Window. When i use the same styles in App.xaml file then they are getting applied
Am i missing anything? Can you please suggest on what needs to be done to get the styles defined in the Resource dictionary are applied to the controls in the MainWindow.xaml?

what i am getting the error each entry must have an associated key? (WPF)

I have read a lot of questions about this, but all of this questions was about VM models, and i dont have the VM model, i am trying to change the language of my application with a ResourceDictionary as is explained in this post.
How to change language in WPF/XAML
and also i saw a lot of examples without specify any key https://learn.microsoft.com/es-es/dotnet/framework/wpf/advanced/how-to-use-a-resourcedictionary-to-manage-localizable-string-resources
and i dont get what i am doing wrong, this is the xaml resource
<Window.Resources>
<Style x:Key="titulo" TargetType="TextBlock" BasedOn="{StaticResource Encabezado}">
<Setter Property="Margin" Value="20"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style x:Key="tipoBase" TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Margin" Value="10"/>
</Style>
<Style x:Key="imagenTitulo" TargetType="Image">
<Setter Property="Height" Value="200"/>
<Setter Property="Source" Value="/images/asistente.jpg" />
</Style>
<Style x:Key="narracion" TargetType="TextBlock" BasedOn="{StaticResource tipoBase}">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style x:Key="botonSalirInicio" TargetType="Button" BasedOn="{StaticResource botonSalir}">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Margin" Value="0 0 10 0"/>
</Style>
<ResourceDictionary>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Idiomas/IdiomasLogin.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary>
</Window.Resources>
The resource file
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ElEscribaDelDJ"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<system:String x:Key="Titulo">Bienvenido a "el escriba del DJ"</system:String>
<system:String x:Key="Narración">a</system:String>
<system:String x:Key="User">Usuario:</system:String>
<system:String x:Key="UserText">Introduzca el nombre de usuario:</system:String>
<system:String x:Key="CheckUser">Recordar Usuario:</system:String>
<system:String x:Key="CheckLogin">Recordar Login:</system:String>
<system:String x:Key="License">Este producto esta bajo la licencia</system:String>
<system:String x:Key="Credits">Creditos</system:String>
</ResourceDictionary>
Other weird thing is that i cant use clr-namespace:System;assembly=mscorlib, when i try to use it, always get an error
Properties of the ResourceDictionary
Embebed Resource
Custom tool: XamlIntelliSenseFileGenerator
and lastly the textblock
<TextBlock Style="{DynamicResource titulo}" x:Name="titulo" Text="{DynamicResource Titulo}"/>
you should put all styles into one ResourceDictionary. at the moment you have too many <ResourceDictionary> declarations, and the outer-most is treated as Resource but doesn't have x:Key, hense the error.
rewrite it like this (<ResourceDictionary.MergedDictionaries> can be written first)
<Window.Resources>
<ResourceDictionary>
<!--<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Idiomas/IdiomasLogin.xaml"/>
</ResourceDictionary.MergedDictionaries>-->
<Style x:Key="titulo" TargetType="TextBlock" BasedOn="{StaticResource Encabezado}">
<Setter Property="Margin" Value="20"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style x:Key="tipoBase" TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Margin" Value="10"/>
</Style>
<Style x:Key="imagenTitulo" TargetType="Image">
<Setter Property="Height" Value="200"/>
<Setter Property="Source" Value="/images/asistente.jpg" />
</Style>
<Style x:Key="narracion" TargetType="TextBlock" BasedOn="{StaticResource tipoBase}">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style x:Key="botonSalirInicio" TargetType="Button" BasedOn="{StaticResource botonSalir}">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Margin" Value="0 0 10 0"/>
</Style>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Idiomas/IdiomasLogin.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

How can I style only those Buttons which are in a DataGrid?

In App.xaml I have styled all my Buttons.
<Style TargetType="Button">
<Setter Property="Margin" Value="3"/>
</Style>
I realized if the Button is in a DataGrid then I not need a margin. I have a lot of DataGrid and I put this code into all of them one by one.
<DataGrid.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="0"/>
</Style>
</DataGrid.Resources>
Is there a more clever way to do this?
You can define Style for DataGrid and within that, add child control style to particular modification.
If you want to add this Style to all the DataGrids, no need to defineKey.
<Style x:Key="dataGrid" TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
Declare a style with the key in the Window.Resources or App.Resources as shown below.
<Window.Resources>
<Style TargetType="Button" x:Key="dataGridButtonStyle">
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Wheat"/>
</Style>
</Window.Resources>
Then apply the style to the control using the StaticResource with the key(in this example key name is dataGridButtonStyle)
<Button Style="{StaticResource ResourceKey= dataGridButtonStyle}" Content="Hello"/>
Please add resource file at Windows or User control level so that it will apply all child controls as below,
<Window.Resources>
<Style TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
<Window.Resources>
or
<UserControl.Resources>
<Style TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
</UserControl.Resources>

Resource Template for UserControls

I'm working on a program with multiple UserControls that should follow the same visual guidelines, as they will function as TabPages of an application to show some data to the user.
Basically, all of the UserControls have two columns. In column #1 I have a label describing which value belongs into the actual control and in the second column follows the control (TextBox, DatePicker, Checkbox etc.) for the user to set:
When I designed the first of those UserControls I ended up with a bunch of Styles that I set in the UserControls resources like this, so all Labels would have the same width, right-aligned text and vice versa:
<UserControl.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</UserControl.Resources>
Now, as I'm about to create all other 60+ UserControls I would like to avoid to add this exact same code over and over again to every single UserControl, just to achieve a consistency in visual style, like same fixed width for labels and so on, as this would be just horrible to maintain (imagine the customer requires all labels just to be 50px less wide...).
Is was wondering if there is any way of setting this formatting stuff once somewhere in the application and then just "import" those settings for my UserControls like this:
Master-file
<Master.Template1>
<Style TargetType="{x:Type Label}">
...
</Style>
<Style TargetType="{x:Type TextBox}">
...
</Style>
<Style TargetType="{x:Type ComboBox}">
...
</Style>
<Style TargetType="{x:Type DockPanel}">
...
</Style>
</Master.Template1>
Other UCs
<UserControl.Resources>
<using Style:Master.Template1/>
</UserControl.Resources>
I already read some stuff about this Application.ResourceDictionary, but I'm not sure if I'm on the right track with that, as I would prefer not to mess around with the code-behind files.
Or should I create my own Control that derives from a UserControl that already has all those values set in it's resources?
Add a new ResourceDictionary file to the project. Put your styles in the ResourceDictionary.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</ResourceDictionary>
Then add the resource dictionary to your UserControl.Resources
<UserControl.Resources>
<ResourceDictionary Source="MyResources.xaml"/>
</UserControl.Resources>
Edit:
Glen Thomas and myself managed to answer the question at the same time. I still leave my own answer up, as the article on MSDN contains some useful further information and upcoming users might find it useful to know how to add a ResourceDictionary in the first place.
Of course this is possible, and as easy as I hoped: ResourceDictionarys were the way to go!
This article in the MSDN poked me into the right direction.
I just added a new ResourceDictionary to my program
and put the reference code into it:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</ResourceDictionary>
After that, I was able to "import" the Dictionary into my UserControl by replacing the UserControl.Resources with this:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
And voilà: formatted controls with the ability to choose if to apply the resource "template" or not and a central place to modify the shared values.
Perfect!

Why Application-Level Resources doesn't work

I want to implement application level resources in my pages, but seems it's not working.
App.xaml:
<Application.Resources>
<Style TargetType="phone:PhoneApplicationPage">
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="shell:SystemTray.ForegroundColor" Value="Black"></Setter>
<Setter Property="shell:SystemTray.BackgroundColor" Value="Transparent"></Setter>
<Setter Property="shell:SystemTray.Opacity" Value="0.5"></Setter>
</Style>
</Application.Resources>
The Page
<phone:PhoneApplicationPage
...
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" >
</phone:PhoneApplicationPage>
I would like the system tray should look the way its styled in App.xaml, but it doesn't.
Thanks!
Application-wide implicit styles work on Windows Phone since Mango. The thing you need to remember is that implicit style is applied to TargetType only, not to its descendants. Your Pages are new classes that inherit from PhoneApplicationPage. What will work is:
<Application.Resources>
<Style TargetType="local:MainPage">
<Setter Property="Foreground" Value="Black" />
<Setter Property="shell:SystemTray.ForegroundColor" Value="Black"/>
</Style>
</Application.Resources>
But obviously you would have to define that for every Page in your project, which makes it useless. For Pages it's best to use Explicit Styles (with x:Key):
<Application.Resources>
<Style x:Key="PageStyle" TargetType="phone:PhoneApplicationPage">
<Setter Property="Foreground" Value="Black" />
<Setter Property="shell:SystemTray.ForegroundColor" Value="Black"/>
</Style>
</Application.Resources>
and for every Page in your project simply:
<phone:PhoneApplicationPage
Style="{StaticResource PageStyle}"

Categories