Style not being picked up WPF - c#

I am trying to set up styles in an external DLL that will be used to define how certain controls should look.
I have a resource dictionary defined in an external DLL that has a style targeted at TextBoxes:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type TextBox}" x:Key="TextStyle">
<Setter Property="Text" Value="Moo"/>
</Style>
</ResourceDictionary>
I then reference this built DLL in another application. This works:
<Window x:Class="HTMLTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GX3Resources;component/Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="45,217,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Style="{StaticResource TextStyle}"/>
</Grid>
</Window>
This does not:
<Window x:Class="HTMLTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GX3Resources;component/Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="45,217,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
</Grid>
</Window>
I would hope the above would pick up the TextStyle as is it a text box and the style is targetted at textboxes.

If you can edit the original style, you can use it for all Textboxes automatically by setting its key property to the target type:
<Style TargetType="{x:Type TextBox}" x:Key="{x:Type TextBox}">
If you can't change the style, try to create another one based on it:
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource TextStyle}"
x:Key="{x:Type TextBox}">
</Style>

Related

How can I use StaticResources defined in App.xaml in other ResourceDictionaries?

I defined some StaticResource styles inside App.xaml to use it across the app:
<Application x:Class="TaskListApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TaskListApp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="primaryColor" Color="#B5B4D9"/>
<SolidColorBrush x:Key="secondaryColor" Color="#393E59"/>
<SolidColorBrush x:Key="backgroundColor" Color="#2a2e42"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="./Themes/CheckboxTheme.xaml"/>
<ResourceDictionary Source="./Themes/TasksTheme.xaml"/>
<ResourceDictionary Source="./Themes/TaskListTheme.xaml"/>
<ResourceDictionary Source="./Themes/MenuButtonTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Using it in MainWindow.xaml is making no errors and works just fine:
<Grid Grid.Row="2"
Background="{StaticResource backgroundColor}"
</Grid>
But when I added it inside a ResourceDictionary (in this case TaskListTheme.xaml), I got an exception:
Exception: Cannot find resource named 'primaryColor'. Resource names are case
sensitive.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="ListBoxItem" x:Key="TaskListTheme">
<Setter Property="Margin" Value="0,0,0,5"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Label Grid.Column="1" Content="{Binding TaskListItemName}"
Margin="0"
Height="50"
Background="{StaticResource primaryColor}"
Padding="10,0,0,0"
Foreground="{StaticResource secondaryColor}"
FontSize="15"
FontWeight="SemiBold"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Center"
BorderThickness="0"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
How can I resolve this kind of problem?
If a resource in TaskListTheme.xaml has a dependency on a resource that is defined in another resource dictionary, you should merge the latter into TaskListTheme.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Colors.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
So move your *Color brush resources to Colors.xaml and then either merge Colors.xaml into the other resource dictionaries or into App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Colors.xaml"/>
<ResourceDictionary Source="./Themes/CheckboxTheme.xaml"/>
<ResourceDictionary Source="./Themes/TasksTheme.xaml"/>
<ResourceDictionary Source="./Themes/TaskListTheme.xaml"/>
<ResourceDictionary Source="./Themes/MenuButtonTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I think mm8's answer is standard way. Said that, you can just move resources directly under Application.Resources to ResourceDictionary inside MergedDictionaries to achieve the same effect.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<SolidColorBrush x:Key="primaryColor" Color="#B5B4D9"/>
<SolidColorBrush x:Key="secondaryColor" Color="#393E59"/>
<SolidColorBrush x:Key="backgroundColor" Color="#2a2e42"/>
</ResourceDictionary>
<ResourceDictionary Source="./Themes/CheckboxTheme.xaml"/>
<ResourceDictionary Source="./Themes/TasksTheme.xaml"/>
<ResourceDictionary Source="./Themes/TaskListTheme.xaml"/>
<ResourceDictionary Source="./Themes/MenuButtonTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Setting the Template property on a UserControl is not supported

I want to make a UserControl which can be used like the example below, however I don't know how to implement that. I found that example somewhere on WPF but seams like this is not supported anymore?
I get following error "WinRT information: Setting the Template property on a UserControl is not supported."
<UserControl
x:Class="Test.Gui.Widgets.WidgetFrame"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Grid BorderBrush="Red" BorderThickness="1">
<ContentPresenter/>
<TextBlock FontSize="100" Foreground="AntiqueWhite">This is a Test</TextBlock>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
Using the control
<local:WidgetFrame>
<TextBlock FontSize="20" Foreground="Green">Content Presentation</TextBlock>
</local:WidgetFrame>
I found the solution by looking into other github repos
Seperate xaml and cs file
WidgetFrame.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="using:Test.Gui.Widgets">
<Style TargetType="local:WidgetFrame">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid BorderBrush="Red" BorderThickness="1">
<ContentPresenter/>
<TextBlock FontSize="100" Foreground="AntiqueWhite">This is a Test</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>
Add it to the App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary Source="ms-appx:///Gui/Widgets/WidgetFrame.xaml"/>
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
WidgetFrame.cs
internal class WidgetFrame : ContentControl
{
public WidgetFrame() { }
}
Now I can place the content with xaml without overwriting the template
<widgets:WidgetFrame Width="200" Height="200">
<Button>Yes!</Button>
</widgets:WidgetFrame>

XAML Style only applied after second instance when using MergedDictionaries

I've observed that when defining a custom button style inside a MergedDictionaries tag, the style is only applied on the second (and all others) instance of the control.
It does not happen when I omit the MergedDictionaries and proceeding ResourceDictionary tag.
Oddly, the Visual Studio (2015) designer shows my expected appearance - it's only at runtime that the error occurs.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<Style x:Key="mybutton" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource mybutton}" TargetType="{x:Type Button}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<StackPanel>
<Button Height="100" />
<Button Height="50" />
</StackPanel>
</Window>
Note this is a completely blank template other than the XAML above:
You're not using the MergedDictionaries right, according to this link:
https://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary.mergeddictionaries.aspx?f=255&MSPPError=-2147217396
"Dictionaries are merged by adding a ResourceDictionary to the generic collection referenced by MergedDictionaries. A merged ResourceDictionary does not have resource elements defined within it in markup. Instead, the merged dictionary is a ResourceDictionary with no markup child elements defined (or with no elements added through code), but with a URI specified for Source. "
You can easily write the styles like this:
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style x:Key="mybutton" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource mybutton}" TargetType="{x:Type Button}" />
</Window.Resources>
<StackPanel>
<Button Height="100" />
<Button Height="50" />
</StackPanel>
</Window>

Styles defined in app.xaml doesn't take effect for the first time [duplicate]

I have a simple WPF window that has 12 buttons on it. I want the same style to be applied to all of them. This code produces the same error:
<Window x:Class="TestApp.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="400" Width="500"
WindowStyle="None" WindowState="Maximized">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/AllResources.xaml"/>
<ResourceDictionary>
<Style TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="100"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="1" Name="Button1"/>
<Button Grid.Column="1" Content="2" Name="Button2"/>
</Grid>
</Window>
The first button does not get the style applied to it, but the second one does. I could set a key and use that on every button, but I would prefer to let WPF handle that for me. I just found out while writing this that when I do not include the outside ResourceDictionary, it works as expected. This will be a problem in the future as my application expands as I have multiple windows that need to share the same resources. The modified code is as follows:
<Window x:Class="TestApp.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="400" Width="500"
WindowStyle="None" WindowState="Maximized">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="100"/>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="1" Name="Button1"/>
<Button Grid.Column="1" Content="2" Name="Button2"/>
</Grid>
</Window>
It also works if I (instead of removing the merged dictionaries) add an x:Key="key" attribute and then explicitly assign that style to each button.
What is the issue here? Why does the first one skip "Button1" and the second not?
I've seen this problem a couple of times before and it's a pretty weird "bug". It happends when you put a Style directly in a ResourceDictionary inside <ResourceDictionary.MergedDictionaries>. The Style is skipped for the first item. This code produces the same result, the Style is skipped for the first ListBoxItem
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Foreground" Value="Green"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<ListBox>
<ListBoxItem Content="Item 1"/>
<ListBoxItem Content="Item 2"/>
<ListBoxItem Content="Item 3"/>
</ListBox>
To get both the styles and MergedDictionaries to work, do it like this instead
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/AllResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Button}">
<Setter Property="FontSize" Value="100"/>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="1" Name="Button1"/>
<Button Grid.Column="1" Content="2" Name="Button2"/>
</Grid>
Although it does not produce an error, according to the documentation:
ResourceDictionary.MergedDictionaries Property
a dictionary used in merged dictionaries should not have content and should use the Source property to refer to another dictionary indirectly. In fact if you put the Style in a resource dictionary and reference both of them in the merge, it works as it should.
We can only speculate why this is not supported but since it isn't, and since the workaround is easy, we can't complain too bitterly except to wish that we received an error at compile time.

How do i create a window that other windows inherit from?

i have a window which is like this
<Window x:Class="pharmacy_Concept.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Login" Height="34" HorizontalAlignment="Left" Margin="12,241,0,0" Name="loginbutton" VerticalAlignment="Top" Width="129" Click="loginbutton_Click" />
<Button Content="Exit" Height="34" HorizontalAlignment="Left" Margin="362,241,0,0" Name="Exitbutton" VerticalAlignment="Top" Width="129" Click="Exitbutton_Click" />
</Grid>
</Window>
I want every new window i have created to have this layout.Do i have to use a resource dictionary for this.If so How?Or do i have to do something else
This is just to grasp the concept.I will be using images and lables later.
You should declare a ControlTemplate that you usually define in a ResourceDictionary. For example:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Style x:Key="{x:Type Window}" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid Background="Red">
<Button Content="Login" Height="34" HorizontalAlignment="Left" Margin="12,241,0,0" Name="loginbutton" VerticalAlignment="Top" Width="129" Click="loginbutton_Click" />
<Button Content="Exit" Height="34" HorizontalAlignment="Left" Margin="362,241,0,0" Name="Exitbutton" VerticalAlignment="Top" Width="129" Click="Exitbutton_Click" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then you should add this to Application resources in app.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Window.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
And in your Window use it like this:
Style="{StaticResource {x:Type Window}}"

Categories