Globally accessible style in class library - c#

I have a class library where I'm defining (basically extending) some controls such as TextBox, Button etc. I'm also using MaterialDesignInXamlToolkit which is used to stylize controls. So my class library will essentially have controls with my own extended functionality and they will look like styles defined in MaterialDesignInXamlToolkit.
Now my question is, since I don't have App.xaml in class library project, where should I write the XAML code to import the styles of MaterialDesignInXamlToolkit, so that they will be applied to my extended controls? What is the place in class library where you can specify styles which are globally accessible and are applied to all the controls?
I searched about this but didn't find what I want. Please help.
Update: Here is my code (not working).
MaterialTextBox.cs
using System.Windows.Controls;
namespace MaterialControls
{
public class MaterialTextBox : TextBox
{
... some extra features here (no XAML file for this class, just this .cs)...
}
}
Themes.xaml (this will contain all the global styles)
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MaterialControls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary>
<Style TargetType="local:MaterialTextBox">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Height" Value="100"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Now I want these styles to apply to MaterialTextBox so that wherever I use it, it should come with this look and featues out of the box.

What is the place in class library where you can specify styles which are globally accessible and are applied to all the controls?
There is none really. In a single resource dictionary, you could use <ResourceDictionary.MergedDictionaries> to import resources that the resources that you define in the resource Dictionary itself are based on, e.g.:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication8">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="...">
<!-- style based on MaterialDesignTheme -->
</Style>
</ResourceDictionary>
But there is no concept of an App.xaml or some kind of "global resource cache" in a class library.

Found the solution.
I was using Class Library project where I actually should have used WPF Custom Control Library project. Here project type is important otherwise you will have to play with .csproj file to make it work.
So now created a new WPF Custom Control Library project (New Project > Windows > Classic Desktop > WPF Custom Control Library template). This project has Themes\Generic.xaml file which will be used as a default location for styles.

There is no concept for a dictionary in the assembly which is automaticaly merged into app.xaml. But for a default control style there is one.
To assign a default style set the DefaultStyleKeyProperty for the control.
static MaterialTextBox() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MaterialTextBox), new FrameworkPropertyMetadata(typeof(MaterialTextBox)));
}
and in Themes\Generic.xaml add the style:
<Style TargetType="{x:Type local:MaterialTextBox}">
...
</Style>
Do not merge Themes\Generic.xaml in your App.xaml
do only add default styles for controls created in this assembly.
The resources in Themes\Generic.xaml are not globaly available, but through the DefaultStyleKeyProperty the resource is found and assigned to the control.

Related

WPF Styles in a BASE class

I am working in WPF .Net 6 I have a Master.exe application and many DLLs, each of which contains functionality for every entity: Customers.dll | Bookings.dll | Vehicles.dll etc. In the each DLL I have WPF/XAML windows, view models, models, etc like a mini complete and isolated application.
I have also created a Base.dll that has the abstract classes that the models and viewmodels inherit. This works fine for a bit of shared code among all the dlls.
Similarly I want a one stop shop for uniform styling across all of the XAML windows.
The question now is; can I have XAML resources and styles in the Base.dll that are used by all the XAML windows in the other dlls?
Sure. Create a WPF Custom Control Library project and define your common XAML resources in one or several resource dictionaries in this project, e.g.:
<!-- Dictionary1.xaml in WpfControlLibrary1.dll: -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="CommonBrush" Color="Red" />
</ResourceDictionary>
Then add a reference to this project from the project where you intend to use the common resources and merge the resource dictionary:
<ResourceDictionary>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource CommonBrush}" />
</Style>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfControlLibrary1;component/Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

How can I make all Resources in one place

I work on C# WPF
I have more than one DataGridView all of them has the same style (Background, row width, column height...etc) but each one has different numbers of columns
So my question is Can I make one style for these grids and share between them?
like css in Web
You can create a resource file in wpf where you can store all your style and template. Don't confuse it with the resource file in the Properties directory. You can add a Resource file by right clicking your project in visual studio and adding an existing xaml file or creating a new one.
After that, define all your styles and templates. Then you only need to include it in your available resources
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="UsingResourceDictionaries.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="myDirectory/myDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Don't forget to give a key to each one of your style and template, so that you can use them in your User controls

Is it possible to have a static list of Styles in Xaml

I would like to have a static list of Styles in Xaml
So far I have tried:
<local:Styles xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp.Core;assembly=MyApp.Core">
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="TextColor" Value="Green" />
</Style>
</local:Styles>
Code Behind
public partial class Styles : List<Style>
{
public Styles()
{
}
}
but when I do
var styles = new Styles();
The class is empty.
As an aside I can't use Application Resources or ResourceDictionary
You can place your styles in a ResourceDictionary (Add -> New Item -> Resource Dictionary):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Your styles here -->
<Style ...
</ResourceDictionary>
Don't forget that you will need to add a reference to it in App.xaml:
<Application x:Class="Your.App.Namespace"
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="pack://application:,,,/Your.App.Namespace;component/Path/To/Dictionary.xaml"/>
...
To get hold of these styles in code-behind, you can use the FindResource method:
Style myStyle = App.Current.FindResource("MyStyleKey") as Style;
One additional Idea that comes to mind
Create a standard Xamarin.Forms.Solution
Mark up the Application XAML with your Styles
Instantiate it and Serialize the Application.Resource to XML
Go back to your MVVMCross app and deserialize it on load and assign it to each page at construction or Application.Current.Resources. Once you have the format for the XML you'd be able to edit it directly and it would be portable from project to project basically a css style sheet(in xml format) for Xamarin Forms might be fun.

WPF's application wide styles in Windows Forms context

We migrate from WinForms to WPF... slowly =)
No we use WPF User Controls with ElementHost.
Is it possible to define application wide resources in this context? In pure WPF Application.Resources stands for it. But there's no WPF App when integrating with WinForms.
You can use a WPF application object even if your project is a WinForms one with a few separate WPF forms or controls. The object won't be precreated for you, but if you manually create it, simply by new App() (or even without a derived class, new System.Windows.Application()), everything in your project will see it.
You can create a common ResourceDictionary and add it to the Resources of your UserControls. That way you just have to change your Styles in one location.
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ResourceDictionary>
and add it to your UserControl using MergedDictionarys
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
or just add it to the Control's Resources like this
<UserControl.Resources>
<ResourceDictionary Source="Dictionary1.xaml"/>
</UserControl.Resources>

WPF Prism - Where to put Resources?

I have a prism application and various modules. I am wondering where is the best place to locate resources such as styles, brush, controltemplates, datatemplates?
Should I make one single resource dictionary and put everything there? Should each module have their own resources? Or each view? I would like to follow the Prism goal of keeping everything modular, but also I dont see the point in re-declaring the same resources in every module...
I develop application with Prism, and I use technique very close to described in Prism's manual. There is YourApplication.Infrastructure project, where you usually place all your shared interfaces etc. So:
I just add project YourApplication.Resources
Create there folder Themes
Create separate xaml file in Themes folder for each group of resources (like Generic.WPF.xaml for standard WPF controls' styles, Generic.Brushes.xaml for brushes etc.)
Create file Themes\Generic.xaml (exactly with this name, it will add huge benefits in the future) with content like
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Generic.Brushes.xaml"/>
<ResourceDictionary Source="Generic.WPF.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Now you can add those resources in any module (you have separate project for it, right?) by adding reference to YourApplication.Resources to that project and adding to your view's xaml:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourApplication.Resources;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Put your not shared resource here -->
</ResourceDictionary>
</UserControl.Resources>
I don't know, maybe this way has some problems, but it works, and works well for me. If anybody can comment somehow this way (pros/cons) - I will be very happy to hear it!
Application-wide resources I usually put in a ResourceDictionary, which is added to either App.xaml or StartupWindow.xaml
Resources for a specific View are usually located with the View. For example, a UserControl that is being used for a CalendarView will contain any custom resources for the Calendar, such as calendar-specific brushes, styles, templates, etc.
I usually don't see a reason to make module-wide resources, but if I ever do I'd have a ResourceDictionary for the Module which can be loaded into the app's merged dictionaries at runtime, or included in individual Views in the Module.
I would like to share some new knowledges. I am using #chopikadze approach. And it is really cool approach. Thanks to you!
However, if you do not want write every time for each control these piece of code:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourApplication.Resources;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Put your not shared resource here -->
</ResourceDictionary>
</UserControl.Resources>
Then you can just declare <ResourceDictionary/> in App.xaml of your Bootstrapper like that:
<Application.Resources>
<ResourceDictionary Source="pack://application:,,,/YourApplication.Resources;component/Themes/Generic.xaml"/>
</Application.Resources>

Categories