Designer ignores BasedOn Style during design time, works during runtime - wpf

There seems to be a bug or limitation on the WPF designer's ability to infer the style to display during design time.
I am skinning my app and have a base window style in my app.xaml:
<Application.Resources>
<Style x:Key="WindowStyleBase" TargetType="ContentControl">
<Setter Property="Background" Value="Red" />
</Style>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}" BasedOn="{StaticResource WindowStyleBase}">
<!-- <Setter Property="Background" Value="Red" /> -->
</Style>
</Application.Resources>
And I skin my window using the static resource WindowStyle :
<Window x:Class="XamlBasedOnBreaker.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" Style="{StaticResource WindowStyle}">
<Grid>
</Grid>
</Window>
Now when I run the application, I see the red background, but during design time in visual studio 2013 and expression blend the background is white (default). The designer does not apply the proper style.
How do I fix this? I have multiple user controls etc on which I want the WindowStyle that's why I subclass the style and use BasedOn. If I move the red color into WindowStyle instead of WindowStyleBase it works, but this would result in too much copy paste code, even if I would use resources for the brushes as I have quite a number of user controls.
Further more I am skinning a dark theme and having a white background during design time is more than inconvenient.

Related

Override Specific Style Properties using Resource Dictionary

I am trying to override the styles of Material Design for Xaml ToolKit as per my requirements, the following is the xaml in app.xaml which i came up with after reading about overriding on the github page of the library, but it seems to be not working and i am not getting why, as i have not much experience working in WPF applications, here is the code i tried:
<Color x:Key="DarkBlueColor">#00479D</Color>
<FontFamily x:Key="MicrosoftYaHei">Microsoft YaHei</FontFamily>
<SolidColorBrush x:Key="WindowBrush" Color="#00479D"/>
<Style x:Key="WindowStyle"
x:Name="WindowStyle"
BasedOn="{StaticResource MaterialDesignPaper}"
TargetType="{x:Type Window}">
<Setter Property="Background" Value="{DynamicResource WindowBrush}"></Setter>
</Style>
For the time being to get familiar i am only trying to change the background of the window, here is the code from MainWindow.xaml:
<Window x:Class="WPFApplication.MainWindow"
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"
xmlns:local="clr-namespace:XCMG.CarMan2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
Style="{StaticResource WindowStyle}"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
<Grid>
</Grid>
</Window>
When i run the application after adding the above code, it throws an exception saying:
Unable to cast object of type 'System.Windows.Media.SolidColorBrush' to type 'System.Windows.Style'.
"MaterialDesignPaper" is a SolidColorBrush and you can't base a Window style on a Brush.
Remove the BasedOn attribute and the x:Name from your Style:
<Style x:Key="WindowStyle"
TargetType="{x:Type Window}">
<Setter Property="Background" Value="{DynamicResource WindowBrush}"></Setter>
</Style>
but i want override MaterialDesignBrush BackGround
Define a new Brush resource with the same key then:
<SolidColorBrush x:Key="MaterialDesignPaper" Color="#00479D"/>

Defining WPF Window style in class library

Currently I am developing some WPF class library, which will have several WPF Windows and trying to create my own window ControlTemplate for these Windows to make more nice design of these windows (inspired by this article: Reusing Control Templates in Resource Dictionaries).
Problem is, then it's a WPF class library not an application assembly, where i can use app.xaml and to define my resource dictionary reference & etc...
Using code below i getting an error: StaticResource reference 'MyWindowStyle' was not found
<Window x:Class="SomeERP.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Style="{StaticResource MyWindowStyle}">
<Window.Resources>
<!-- My Window Style -->
<Style x:Key="MyWindowStyle" TargetType="Window">
<Setter Property="Background" Value="Transparent" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Opacity" Value="0.95" />
<Setter Property="Template" Value="{StaticResource MyWindowTemplate}" />
</Style>
<!-- Window Template -->
<ControlTemplate x:Key="MyWindowTemplate" TargetType="{x:Type Window}">
<Grid>
</Grid>
</ControlTemplate>
</Window.Resources>
</Window>
I suspect i get this error because in my case it's not predeclared before Window declaration as in application's case in app.xaml which i don't have in class libary. I am pretty new in WPF and just starting to use WPF design possibilities.
If you need the style only once, the solution is pretty simple: Just define the style in-place
<Window.Style>
<!-- My Window Style -->
<Style TargetType="Window">
...
</Style>
</Window.Style>
However, if you need the style in more than one window, it is reasonable to define the style in a resource dictionary. Then you can integrate the resource dictionary in the window's resources and set the style accordingly:
<Window.Resources>
<!-- My Window Style -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
<!-- path to the resource dictionary -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resource>
<Window.Style>
<StaticResource ResourceKey="MyWindowStyle"/>
</Window.Style>
Looks like i've found solution to my problem in this post: Assembly-wide / root-level styles in WPF class library and according to this post What's the difference between StaticResource and DynamicResource in WPF?
A StaticResource will be resolved and assigned to the property during the loading of the XAML which occurs before the application is actually run. It will only be assigned once and any changes to resource dictionary ignored.
A DynamicResource assigns an Expression object to the property during loading but does not actually lookup the resource until runtime when the Expression object is asked for the value. This defers looking up the resource until it is needed at runtime. A good example would be a forward reference to a resource defined later on in the XAML. Another example is a resource that will not even exist until runtime. It will update the target if the source resource dictionary is changed.
That was what i needed, as i have class library, i don't have app.xaml and can't predeclare resources for Window. I just need to use DynamicResource rather than StaticResource to get it working.
Thanks for attention :)
Just add the external assembly:
<Application.Resources>
<ResourceDictionary>
Source="/MyAssemblyName;component/MyResources.xaml"
</ResourceDictionary>
</Application.Resources>

Apply themes to wpf and use styles

I am trying to apply a theme to a bunch of wpf projects. There is one assembly containing the generic.xaml and different applications. As far as i understand i can't use the ThemeInfo attribute with ResourceDictionaryLocation.ExternalLocation because the name have to be the same as my program but I have more than one program...
So I search and found that I only have to include the dictionary as MergedDictionary in the app.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ClassLibrary1;component/Themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
This basically works. But if I use a style for the controls it will not apply the generic.xaml style anymore:
generic.xaml in ClassLibrary1.dll
<ResourceDictionary x:Class="ClassLibrary1.Themes.generic"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Black" />
</Style>
Window in program
<Window x:Class="Theming.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>
<Style TargetType="Button"
x:Key="ButtonGreenTextStyle">
<Setter Property="Foreground"
Value="Green" />
</Style>
</Window.Resources>
<Grid>
<Button Style="{DynamicResource ButtonGreenTextStyle}" Content="Test" />
</Grid>
</Window>
What I have to do, that WPF will understand the style in my generic.xaml as basestyle for all buttons (I know I will also have to write a ControlTemplate; the above code is just for simplicity)
Two things I would try
Create a generic ButtonBase style/template to set the look of all
buttons
Try using a BasedOn attribute on the ButtonGreeTextStyle,
basing it on an existing style.
I found another solution. You have to write styles based on a custom markup:
This will apply the current theme style. The code for this MarkupExtension can be found here:
How do I alter the default style of a button without WPF reverting from Aero to Classic?

Silverlight: Change style for state

My App.xaml looks like this:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="mySilverlightApp.App"
>
<Application.Resources>
<Style x:Name="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="FontFamily" Value="Calibri.ttf#Calibri"></Setter>
</Style>
</Application.Resources>
As you can see, I'm trying to apply custom styling with <Setter> tags to ComboBoxes in my app. But I want to apply styling for different states of the ComboBox (MouseOver, etc).
How can I do this?
To accomplish this, you'll have to create a control template in your implicit style. Something like the following:
<Style x:Name="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
....
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can refer to this link for the default styles/controltemplates for the combobox: http://msdn.microsoft.com/en-us/library/dd334408(v=vs.95).aspx
A great way to get started re-templating controls is using Blend. You can right click a control you have dragged onto the artboard and use the "Edit Template -> Edit a Copy" command. This will create a default controltemplate for you (the same one shown in the link I provided).
From there you can edit the mouse-over state in Blend by using the States tab.
There's alot going on here, but this should get you started on the right path.

WPF: Style ListBoxItem to unify colors

I am starting with WPF development on a touch device. Although .NET and WPF seem to be an amazing technology, I am somewhat lost.
I am developing a generic control. I defined an UserControl which contains a Grid, some buttons and a SurfaceListBox. In the actual C#-code I am handling events and add new elements to the list box by manipulation the listItems-Attribute. This works fine so far.
Now I would like to change the style of the list items - I would like to make their background transparent if they are not selected, and completely white if they are. Unfortunately the following piece of code simply does not work. It just sets the background color of the list item text to white, but not the whole item.
Update: Now it works!
<UserControl x:Class="SGEditor.MyControl"
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"
mc:Ignorable="d"
xmlns:my="http://schemas.microsoft.com/surface/2008" UseLayoutRounding="True">
<UserControl.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<my:SurfaceListBox Width="300" Height="300" />
</Grid>
</UserControl>
Thank you!
Hans
I don't know exactly how to do what you want to do, but I'm pretty sure you can't reassign a static system value like you're trying to do in x:Key. That's just a name you use to reference the resource later in the xaml, like MyBackgroundColor or whatever.
I think what you need to do is something with triggers in the style for your control that set the appropriate properties for the elements you want to change. Hopefully someone else will shed more light on that, since I rarely do that fancy stuff. =)

Resources