I use <FluentTheme Mode="Dark" /> for my application. I really like it but i want to change part of the design. For example swap the background to a bright pink.
I tried overriding the style like this:
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Avalonia.Test"
x:Class="Avalonia.Test.App">
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
<Application.Styles>
<FluentTheme Mode="Dark" />
<Style>
<Style.Resources>
<Color x:Key="ThemeBackgroundColor">#CCFF0068</Color>
<SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{DynamicResource ThemeBackgroundColor}" />
</Style.Resources>
</Style>
</Application.Styles>
But sadly it doesnt work. No errors are thrown but the change doesnt apply. Does anyone have a tip on how to only change part of the FluentTheme of avalonia?
For the Fluent theme the resource name is SystemControlBackgroundAltHighBrush.
I suggest overriding the resource instead of using style in your App.xaml -
<Application.Resources>
<SolidColorBrush x:Key="SystemControlBackgroundAltHighBrush" Color="#CCFF0068"/>
</Application.Resources>
Related
I am using Material Design to style my WPF app. I have used the following code to style a tab view:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Material Design -->
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
<!-- Styles -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />-->
</ResourceDictionary.MergedDictionaries>
<!-- Tab Controller Primary Styles -->
<SolidColorBrush x:Key="PrimaryHueLightBrush" Color="#212121"/>
<SolidColorBrush x:Key="PrimaryHueLightForegroundBrush" Color="#212121"/>
<!-- This causes a clash between the tabview and the textbox colors -->
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="#212121"/>
<!--<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="#BB86FC"/>-->
<SolidColorBrush x:Key="PrimaryHueMidForegroundBrush" Color="#FFFFFF"/>
<SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="#212121"/>
<SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="#212121"/>
</ResourceDictionary>
<!-- Tab Controller Secondary Styles -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="SecondaryAccentBrush" Color="#BB86FC"/>
<SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="#BB86FC"/>
</ResourceDictionary>
<ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}" />
</ResourceDictionary>
The issue I have is that to style the TabController primary style, it changes the color of the TextBox in my application.
When I apply a dark color to style the tab view, the TextBox loses its purple highlight.
But now in the second image, when I change the color back to purple for the TextBox, the TabView looks horrific.
They both depend on the same dictionary key for their styles. Is there a way I can change the x:Key value depending on what object type it is applied to? What is the best way to preserve the styles I need for both components.
This is for my university dissertation so I appreciate the help!
All the best.
The Material Design brushes are used in various styles of controls using DynamicResource. That means if you replace or register a brush with the same x:Key at runtime, all dynamic references will be adapted and the change will be applied to all controls in scope of the resource dictionary where you defined it.
In general, you would have to copy the default style and template for the control that you want to apply the changed color to and adapt it, e.g. by creating a separate brush and using it instead of the original, given the values are assigned in the control template directly instead of template bindings.
In case of the TabablzControl there might be an easier way. From its default style at GitHub, I can only see one usage of PrimaryHueMidBrush that is set as BorderBrush in a Setter. You can ovewrite this in your style.
<Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}">
<Setter Property="BorderBrush" Value="#212121"/>
</Style>
Of course, you could create a custom brush and reference it via DynamicResource instead of hardcoding it.
<Setter Property="BorderBrush" Value="{DynamicResource MyCustomPrimaryHueMidBrush}"/>
I am in a situation where I have defined 3 colors in my program. They are defined in App.xaml as such:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="Aero">
<Color x:Key="AccentColor">#3399ff</Color>
<Color x:Key="AccentDarkColor">#236bb2</Color>
<Color x:Key="AccentDarkerColor">#1e5b99</Color>
<SolidColorBrush x:Key="AccentBrush" Color="{DynamicResource AccentColor}" />
<SolidColorBrush x:Key="AccentDarkBrush" Color="{DynamicResource AccentDarkColor}" />
<SolidColorBrush x:Key="AccentDarkerBrush" Color="{DynamicResource AccentDarkerColor}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Now, I want these colors to be changeable, so there are areas of my program where I change them programmatically:
Application.Current.Resources["AccentColor"] = color;
Application.Current.Resources["AccentDarkColor"] = color;
Application.Current.Resources["AccentDarkerColor"] = color;
This however poses a problem, since I also have storyboards defined in my application that allow the application to fade (via a ColorAnimation) from one color to another (for instance fading from AccentColor to AccentDarkColor).
When these storyboards do this, they use a StaticResource since a DynamicResource can't be used (because the Storyboard has to be freezable) for WPF to do its thing.
What did I try?
I tried moving the storyboards to App.xaml as well, and then (in my BeginStoryboard refer to a DynamicResource of the storyboard:
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{DynamicResource BackgroundToAccentBorderToAccentDarkTransitionStoryboard}" />
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
However, when I then programmatically change the storyboards, they don't change when the DataTrigger gets re-executed, despite it being a DynamicResource.
What can I do?
It should be very easy to do this but I haven't found the information that I need. What I want is as simple as changing the color of the slider bar:
I'm using ModernUI and the default bar color is very similar to my background and I want to make it a bit lighter.
You should be able to change it editing the template.
Right click your Slider, Edit Template -> Edit Copy.;.
A new window will appear asking you where VS should put the XAML code for the ControlTemplate and Styles. Chek the tags and such.
Good luck!
Edit:
Ok, here it goes.
Assuming that you already have a ModernUI App, create a new folder called Assets, right click it Add -> New Item... -> ModernUI Theme. Call it whatever you like it.
Inside the newly created XAML file insert these SolidColorBrush under the AccentColor Color tag:
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Red" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Red" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Red" />
Each one of these represents a state of the Thumb (the slider "rectangle"). After that open your App.xaml file and include your theme there (this is what my file looks like):
<Application x:Class="ModernUIApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
<ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
<ResourceDictionary Source="/Assets/ModernUI.Theme1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The <ResourceDictionary Source="/Assets/ModernUI.Theme1.xaml" /> bit represents my theme.
Setting all the colors to Red, this is what it looked like:
I guess that's more clear!
Hope you like it.
EDIT:
It will change when you apply your theme. But, as you're familiar with styles, I'm sending the complete template. What you can do is create a UserDictionary with only this template and when you you want to use it, change the slider Template property. You'll want to change only the Thumb Tags. Pastebin code
And if you want to change only THIS one put the template between <Windows.Resources> or <Slider.Resources> - Another option would be create your own control
I found two approaches:
You can customize your slider by insert corresponding brushes in
appropriate Slider.Resources section.
You can add brushes to separate xaml file with dictionary and then
merge it with corresponding slider in the Slider.Resources. In some cases it fits better because you can change colors of few controls at once.
Any does not need to changing of the control's template.
Both approaches are presented below:
Page1.xaml
<Grid Style="{StaticResource ContentRoot}">
<StackPanel>
<!-- Slider with default theme and colors from ModernUI -->
<Slider/>
<!-- Slider with custom colors from approach 1 -->
<Slider>
<Slider.Resources>
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Green" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Green" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Green" />
</Slider.Resources>
</Slider>
<!-- Slider with custom colors from approach 2 -->
<Slider>
<Slider.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Slider.Resources>
</Slider>
</StackPanel>
</Grid>
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="SliderSelectionBackground" Color="Blue" />
<SolidColorBrush x:Key="SliderSelectionBorder" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackground" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundDisabled" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundDragging" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBackgroundHover" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorder" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderDisabled" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderDragging" Color="Blue" />
<SolidColorBrush x:Key="SliderThumbBorderHover" Color="Blue" />
</ResourceDictionary>
As result you get following:
Foreground property is used to fill the "completed" part of the slider with a particular color. (Background does the uncompleted part.)
<Slider Value="40" Maximum="100" Foreground="Red" />
Here you have the templates you should use: Slider Styles and Templates
The property you are looking to edit is the TrackBackground.BackGround.
If you define a style for this control template and put it either in you app.xaml or in the window.resources or in any other file, as long as you give it a key you can use it in a specific slider through the "Style" property of that slider using that same key.
Windows 8.1 Store/Phone Apps.
Add this to the App.xaml and change the color values to your liking:
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="#FFFF0000" />
<SolidColorBrush x:Key="SliderTrackDecreasePointerOverBackgroundThemeBrush" Color="#FF00FF00" />
<SolidColorBrush x:Key="SliderTrackDecreasePressedBackgroundThemeBrush" Color="#FF0000FF" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrastBlack">
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrastWhite">
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
You probably only want to change the slider for the default theme and probably only the three color values shown above. For all colors / resources that you can change, see this link at MSDN: Slider styles and templates.
For what it's worth, the only way I could change the Slider Thumb color on Win10 UWP for Phone was to overwrite the System Foreground brush. (You can also apparently completely re-template the whole Slider)
So, I put into my App.xaml
<Application
x:Class="App1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
RequestedTheme="Dark">
<Application.Resources>
<SolidColorBrush x:Key="SystemControlForegroundAccentBrush" Color="White" />
</Application.Resources>
</Application>
The addition to Application.Resources is the really important thing here. It's where we're overwriting the Foreground color for ALL common elements, like Checkbox, ContentDialog, ProgressRing, etc.... So, that's the downside to this method too.
Changing the Thumb color on a Slider is a known problem point for XAML UWP. Microsoft has plans to make it easier in the immediate future.
How can WPF resources - including styles, templates, etc. - be organized, so that I can use them across Windows, Pages or even Projects. What options do I have to achieve maximum re-usability of my resources and a maintainable structure (for example one file per Template)?
For example: I am creating a WPF application and I want to use a TabControl, but I want to make major changes to it. So I could create a style in and apply it to the TabControl and TabItem. That's ok, but where can I place my resources to keep my Window XAML clear and have the style accessible from other Windows or projects as well?
I found that I can add it to App.xaml but that is only a solution for one project and allows sharing just between items of this project. Also, I think it would be better to have these templates a little separate from other code, than placing it all in some page or app.xaml?
I usually create a seperate styling project, which I reference from the projects, which I want to style. The styling project has a fixed structure like this:
For every control, I create a styling ResourceDictionary. For example for my buttons:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
</Style>
<Style x:Key="ToolbarButton" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Transparent"></Setter>
</Style>
</ResourceDictionary>
In one main ResourceDictionary, I merge all the other dictionaries, in this case in the file IncaDesign.xaml, which you can see in the picture above:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Commons.Controls;assembly=Commons">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Converter/Converter.xaml" />
<ResourceDictionary Source="Styles/Button.xaml" />
<ResourceDictionary Source="BitmapGraphics/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Default Styles -->
<Style TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}"></Style>
</ResourceDictionary>
Notice how I defined the default styles, which are applied automatically, unless you specify otherwise. In every window or control, that you want to style, you only need to reference this one ResourceDictionary. Note the definition of the source, which is a reference to the assembly (/Commons.Styling;component...)
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Commons.Styling;component/IncaDesign.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Default styles will be set automatically now, and if you want to access a resource explicitly, you can do this, using StaticResource.
<Viewbox Height="16" Width="16" Margin="0,0,10,0">
<ContentControl Content="{StaticResource FileIcon32}" />
</Viewbox>
This is very nice solution in my opinion, which works for very complex solutions, including modular solutions, for example built with PRISM.
A ResourceDictionary is for what you are looking.
Here is an explanation for how to use them within and across projects.
You can create a project that contains Resource Dictionaries, either in your solution or in a separate one. Your project will be a Class Library type and can then easily be .dll referenced from any other project. Here is an article describing this: Resource Dictionary Article
As I have multiple Windows in my application, I am looking for a solution that does not require me to set a binding on each Window.
I created a ResourceDictionary which has a style for the Window Background:
<Style TargetType="{x:Type Window}">
<Setter Property="Background" Value="AliceBlue"/>
</Style>
In my XAML, I set the ResourceDictionary:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Templates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
There is no error, but my Window color stays white.
This appears to be caused by a combination of the order in which WPF loads/processes styles from nested ResourceDictionary, and the specifics of the Window class.
Assume MainWindow is defined as per your post. Now put the following in Templates.xaml:
<Style TargetType="{x:Type Window}">
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="{x:Type Window}" x:Key="myStyle">
<Setter Property="Background" Value="Green"/>
</Style>
If MainWindow has no style defined, then you will see that in the designer it appears with a red background. The designer is parsing the whole Xaml and loading the resource dictionary, and then drawing the results. The style is read before the window is drawn, and so the red background is applied.
When you run the application, the window is created before the ResourceDictionary is applied. It looks for a default style (a style with x:Key="{x:Type Window}") before the nested ResourceDictionary is processed, and finds nothing. Therefore at runtime, the window appears with default colour. (This is the behaviour described in the comments above.) Remember that the style with x:Key="{x:Type Window}" has a default value that matches the Windows style.
This is borne out if you use myStyle explicitly. If you add to your Window definition the attribute Style="{StaticResource myStyle}" you'll find that the designer fails, but you also get a run-time error, because myStyle hasn't been created at the time that the Window needs it. If you switch to Style="{DynamicResource myStyle}" then you'll see that it works as you hope, because DynamicResource will update once the ResourceDictionary has been parsed and the style included.
So, applying this, you can fix the problem in one way by adding this to your Window element: Style="{DynamicResource {x:Type Window}}" - but this is cludgy. The better solution is to include your resource dictionary in the app.xaml file, where it will be parsed before any window is opened and thus available to all:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Templates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The real issue here is that your Window is not really a Window: it is a class that derives from Window and will in fact be MainWindow, Window2, etc... This means that the automatic style wireup for a Window will never work in this way, and some level of manual binding will unfortunately always be required.
This is the solution I used in my application. It lets me keep all my window styles together, and requires just a couple lines after the <Window.Resources> section.
Do your Style like so:
<Style x:Key="MyWindowStyle">
<Setter Property="Window.Background" Value="AliceBlue"/>
</Style>
Then, in your Window, after </Window.Resources> include the following:
<Window.Style>
<Style BasedOn="{StaticResource MyWindowStyle}"/>
</Window.Style>
Add a new brush in your resource dictionary
<SolidColorBrush x:Key="WindowBackground" Color="AliceBlue" />
and in your WPF window simply set the required resource to the window background property
<Window x:Class="GDD.Presentation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300"
Background="{StaticResource WindowBackground}">