Catel: Create new DataWindowButtonStyle based on another 3rd party style - c#

REF: Catel docs
Using Visual Studio 2013, .NET 4.5.1, Catel 4.4.
I have a DataWindow with the default Close button. I would like to style that button using the MahApps.Metro Flat Button style. If I had direct access to the DataWindow Close button (I think it's created at runtime), I'd apply the Flat Button style in the XAML, but I don't.
In the Catel docs, the comment says we should specify our own DataWindowButtonStyle. Could I get an example of creating a new DataWindowButtonStyle where I can base it on the MahApps.Metro Flat Button style?
Please let me know if you have any questions or need more information.
Thanks!
Edit: Here's what I've tried:
<catel:DataWindow.Resources>
<!-- Compile Error: A 'DynamicResourceExtension' cannot be set on the BasedOn property of type 'Style'.
<ResourceDictionary>
<Style x:Key="DataWindowButtonStyle" BasedOn="{DynamicResource MetroFlatButton}" />
</ResourceDictionary>
-->
<!-- This compiles and runs, but doesn't work.
<ResourceDictionary>
<Style x:Key="DataWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow" />
</Style>
</ResourceDictionary>
-->
<!-- This compiles and runs, but doesn't work.
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Catel.MVVM;component/themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="DataWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow" />
</Style>
</ResourceDictionary>
-->
<!-- Compiles and runs, but doesn't work. -->
<Style x:Key="DataWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow" />
</Style>
</catel:DataWindow.Resources>

You can simply define a new DataWindowButtonStyle resource and it should be applied automatically.

The custom DataWindowButtonStyle must be defined in App.xaml application resources.
App.xaml:
<Application.Resources>
<Style x:Key="DataWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="MinHeight" Value="50"/>
</Style>
</Application.Resources>
I don't know why setting background property is not working. But other properties are working.

Related

How to easily allow users to update Styles used be elements in XAML (UWP)

This is for a Windows 10 UWP. I need to allow users to update values on Styles that are associated with elements used throughout the application (i.e allow users to change the font size of various textblocks, background color stackpanels etc.) .
I currently have all my Styles in a separately file.
My App.xaml is as below:
<Application
x:Class="MyTestApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
My Styles.xaml (partial) is as below:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:MyTestApp.Views"
xmlns:x1="using:System">
<Style x:Key="HeaderTextBlocks" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="10,4,0,0"/>
</Style>
<Style x:Key="RegularTextBlocks" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="0,0,0,0"/>
</Style>
</ResourceDictionary>
I refer to these styles on controls throughout the application using like this:
<TextBlock Style="{StaticResource HeaderTextBlocks}" />
I have created a Settings page (settings.xaml) which has textboxes for the users to update various style settings.
But I am not sure how I could bind these to the settings on the various styles on the styles.xaml file so that the styles are updated and the controls referring to the styles are updated when the user changes the value.
<TextBox Header="Font Size of Header TextBlocks" Text="{x:Bind HeaderTextBlocks.FontSize ???, Mode=TwoWay}" />
<TextBox Header="Font Size of Regular TextBlocks" Text="{x:Bind RegularTextBlocks.FontSize???, Mode=TwoWay}" />
Could someone please point me in the right direction? I am trying to do this with minimal (or no code behind) as possible.
Unfortunately this kind of user-defined styling is not easily available in UWP. You can however implement a kind of styling solution using data binding.
First step is to create a class like CustomUISettings which implements INotifyPropertyChanged and has properties like HeaderFontSize, etc.
Now on app start create an instance of this class and add it as app resource:
Application.Current.Resources["CustomUISettings"] = new CustomUISettings();
Now you can bind to the properties in this class anywhere in your code:
<TextBox FontSize="{Binding HeaderFontSize, Source={StaticResource CustomUISettings}}" />
You must use the classic {Binding} markup extension, because {x:Bind} does not support Source setting.
To modify the UI settings you can just retrieve the instance anywhere and set the properties as you see fit:
var customUISettings = (CustomUISettings)Application.Current.Resources["CustomUISettings"];
customUISettings.HeaderFontSize = 50;
You must make sure that all properties in CustomUISettings class fire the PropertyChanged event. You can see how to implement INotifyPropertyChanged interface for example here.

WPF Style at Windows or App level yields different results

I'm trying to learn Styling in WPF and encountered a funny thing:
There is a difference when I apply a style at application or (main) window level.
When I define the following resource in the App.xaml:
<Application.Resource>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Application.Resource>
the GroupBox caption is bold and italic.
When I instead define the styling in the MainWindow.xaml:
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Window.Resources>
The GroupBox caption box is only bold and not italic.
Can anybody explain this behavior?
In picking TextBlock you have unearthed something. TextBlock is not derived from Control, and thus behaves slightly differently.
See https://stackoverflow.com/a/27065140/4258144 :
there is a curious rule in WPF implicit styles are only inherited
across template boundaries by elements which inherit from the Control
class
I guess you can add to that, "unless it is globally specified in App.xaml".
UPDATE:
Following comments, here's a look at a GroupBox visual tree, taken from Snoop.

How can I change the default style of WPF controls for a single assembly?

I've written a WPF plugin for some off-the-shelf product, and in this plugin I've used a theme/style to change the minimal width of all buttons like so:
<Style TargetType="Button">
<Setter Property="MinWidth" Value="80" />
</Style>
In the newest version of said off-the-shelf product they migrated from winforms to WPF themselves. Now when my plugin is loaded the style that previously just affected my plugged-in forms now affects all buttons in the application. This renders most UI's unusable.
I know I can use dictionary key based resources to make this style specific to my buttons, but this means I have to change each and every button in my plugin by hand, as well as not forget to set the style of each button in the future (and other elements this problem applies to). There are other options to make the style specific to a set of buttons, as seen in Is it possible to set a style in XAML that selectively affects controls? But I'm looking for a way to let my style affect only those of my plugin (so a bit more coarse than talked about in the referenced question). This plugin consists of multiple windows/views (tied together with Caliburn.Micro).
Is there a way to easily scope a style to for instance an assembly or namespace? I'd really like to define my resources just once. Currently it's defined at the Application.Resources level, if there's one more appropriate I'd like to hear that too.
With a ResourceDictionary, we can set default style wich will be applied without define style in Xaml.
DictionayNew.xaml :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<!-- default button -->
<Style TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="80" />
</Style>
<!-- new button style -->
<Style x:Key="ActionButton" TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Height" Value="23" />
</Style>
<!-- new button style based on previous style -->
<Style x:Key="BigActionButton"
BasedOn="{StaticResource ActionButton}"
TargetType="{x:Type Button}">
<Setter Property="MinWidth" Value="150" />
<Setter Property="Height" Value="30" />
</Style>
</ResourceDictionary>
In your Xaml, use the dictionary :
<Window x:Class="CheckDoublonImageBing.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 Source="DictionaryNew.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
</Grid>
</Window>
Then, use Button as usual or with new style
<Button Content="Refresh" />
<Button Content="Delete selected" Style="{DynamicResource ActionButton}" />
With no style defined, button will have default style defined in the dictionary.
EDIT :
You can set merged dictionary by code like this :
ResourceDictionary myResourceDictionary = new ResourceDictionary();
myResourceDictionary.Source = new Uri("DictionayNew.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
You need to specify a Key for your Style and apply the Style to all your Buttons.
<Style TargetType="Button" x:Key="MyButtonStyle">
<Setter Property="MinWidth" Value="80" />
</Style>
<Button Style="{StaticResource MyButtonStyle}"/>
Without a Key the Style is used for all Buttons in the application (as you have already noticed).

VS2012: An Error occurred while finding the resource dictionary

I am working on a Windows Phone 8 project, project was created using C# Windows Phone Blank App from templates, I have added a simple ResourceDictionary entitled GPResources.xaml(manually created) and then referenced that file in App.xaml, the file I created is located in the root folder, code below:
<!-- VS2012 saying FontFamily and FontSize properties are not recognized or are not accessable, not sure why... ANYONE?-->
<Style TargetType="{StaticResource GPFontFamily}">
<Setter Property="FontFamily" Value="CalifR.ttf"/>
</Style>
<Style TargetType="{StaticResource GPFontSizeSmall}">
<Setter Property="FontSize" Value="12"/>
</Style>
<Style TargetType="{StaticResource GPFontSizeMedium}">
<Setter Property="FontSize" Value="18"/>
</Style>
<Style TargetType="{StaticResource GPFontSizeLarge}">
<Setter Property="FontSize" Value="22"/>
</Style>
App.Xaml:
<ResourceDictionary x:Key="GPResources">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GPResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
VS2012 keeps giving me the error: "An Error occurred while finding the resource dictionary" in the App.xaml file, I cannot think of what the problem is, can anyone point me in the right direction?
Cheers
I think you created Resource Dictionary in a wrong way. Following is an example on how to define a style named "GPTextBlock" that will style a TextBlock where it applied, to have a FontSize = 12 and displaying text in Red color.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBlock" x:Key="GPTextBlock">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style ...>
...
...
</Style>
....
....
</ResourceDictionary>
And overall structure of GPResources.xaml content you had should look like above sample structure. This is one of resources I found explaining about ResourceDictionary you may want to take a look : MSDN Blog

Specify Style from App.Resources to Theme file

Here's a simple thing with which I am struggling with :
I have a style specified in my App.Resources
<Application.Resources>
<Style TargetType="{x:Type igDock:PaneToolWindow}">
<Setter Property="Background" Value="Red"/>
</Style>
</Application.Resources>
I would Like to move this into my theme file by trying something like this.
<SolidColorBrush x:Key="{ComponentResourceKey {x:Type DockManager:PaneToolWindow}, defaultBackground}" Color="Red" PresentationOptions:Freeze="true" />
Of course I am doing something terribly wrong here, My intention is to have all floating windows a default style.
Why use a solid color Brush? The way you had it initially would have worked fine if placed in your custom XAML file.
Just put
<Style TargetType="{x:Type igDock:PaneToolWindow}">
<Setter Property="Background" Value="Red"/>
</Style>
...in your style file.

Categories