How to use style defined in another xaml file inside a style - wpf

I had MultiSelComboBoxStyle defined in a xaml resource file, and in another xaml resource file, I have
<Style x:Key="DataGridDemoStyle" TargetType="{x:Type DataGrid}">
....
<ComboBox x:Name="ccBox" Grid.Row="0" Grid.Column="1" Width="9" Height="18" VerticalAlignment="Top" Margin="0" Style="{StaticResource MultiSelComboBoxStyle}" Panel.ZIndex="1"/>
....
</Style>
I put every xaml in App.xaml and the compiler did find this MultiSelComboBoxStyle style , but debugging the program says MultiSelComboBoxStyle was not found. In App.xaml
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DataGridCustomizations.xaml" />
<ResourceDictionary Source="MultiSelComboBoxStyle.xaml"></ResourceDictionary>

It turns out I need to do
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MultiSelComboBoxStyle.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
If needs to use styles from different resource files.

Related

Avalonia Ui equivalent to ImageResource

I try to define an ImageSource with AvaloniaUi. In WPF I was going this way:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ImageSource x:Key="Icon">path/to/image/image.png</ImageSource>
</ResourceDictionary>
And then referenced to it like this:
<Image Source="{StaticResource Icon}"/>
How can i archive the same in Avalonia?
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:imaging="clr-namespace:Avalonia.Media.Imaging;assembly=Avalonia.Visuals">
<UserControl.Resources>
<imaging:Bitmap x:Key="MyBitmap">
<x:Arguments><x:String>icon.png</x:String></x:Arguments>
</imaging:Bitmap>
</UserControl.Resources>
<Image Source="{StaticResource MyBitmap}"
Width="100" Height="200"
Stretch="None"/>
</UserControl>
Note that this only works with physical paths, since converter isn't involved anymore.
You can also try to experiment with attached properties that will accept your own image holder.

Set value in xaml using class field

I have a DataGrid as:
<DataGrid Grid.Row="4" Name="grvAllCry" Margin="5,5,5,5" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Rank" Width="10*" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Rank}" Foreground="#46BF6E"></Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
As you can see, I set Foreground of row of DataGrid is "#46BF6E". But I have many DataGrid and I want to re-use this variables. Something like:
public static class Config
{
public static string MyGreen = "#46BF6E";
public static string MyRed = "#D14836";
public static string MyBlue = "#428BCA";
}
Is there a way I can create a class like that and use it's variable in many different xaml files? For examples:
<Label Content="{Binding Rank}" Foreground="MyGreen"></Label>
I dont know how to call variable from .cs file while in xaml file, pls help me.
You could create a new ResourceDictionary where you define a Brush resource:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="myBrush" Color="#46BF6E"/>
</ResourceDictionary>
If you want to be able to reference this resource throughout your entire application, you can then merge this resource dictionary into your App.xaml:
<Application x:Class="WpfApp1.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="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
...and reference the resource from any view using the StaticResource markup extension:
<Label Content="{Binding Rank}" Foreground="{StaticResource myBrush}"></Label>
it is possible to referense static property or field (including const fields) using {x:Static ...} extension. For Config class it should be:
<Label Content="{Binding Rank}" Foreground="{x:Static myNameSpace:Config.MyGreen}"/>
xaml file should include namespace definition of Config class (xmlsns:myNameSpace="....")
However, reusable elements are usually defined as Resources. Resources which are visible across the application are defined in App.xaml:
<Application.Resources>
<SolidColorBrush x:Key="MyGreen" Color="#46BF6E"/>
<SolidColorBrush x:Key="MyRed" Color="#D14836"/>
<SolidColorBrush x:Key="MyBlue" Color="#428BCA"/>
</Application.Resources>
such resources can be used from StaticResource/DynamicResource extension:
<Label Content="{Binding Rank}" Foreground="{StaticResource MyGreen}"/>

How to Define Common Resources Across WPF Applications (including templates)?

I am looking for a way to define a WPF resource (for now, to be used as a static resource) that is accessible from everywhere within my application.
My resource is defined in this resource dictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="flatButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="4"/>
</Style>
</ResourceDictionary>
The selected answer to this question indicates that I must merge that resource dictionary into my App.xaml file (of a project called AppWideResources):
<Application x:Class="AppWideResources.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
At first, this seems to work; the button in this window is appropriately styled in a flat way with an extra-thick border:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
</StackPanel>
</Window>
However, this stops working as soon as I use my shared resource in a control template:
My (extremely simplified, for the purpose of this question) control:
using System;
using System.Windows;
using System.Windows.Controls;
namespace AppWideResources
{
public class MyControl : Control
{
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
}
}
}
... and the corresponding Themes\Generic.xaml file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources">
<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
This control is then inserted into my window:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
<local:MyControl/>
</StackPanel>
</Window>
If I run this, a XamlParseException is thrown, saying that the static resource flatButtonStyle cannot be found.
The only workaround I have found is by explicitly merging the common resource dictionary into the local resource dictionary of the control template:
<ControlTemplate TargetType="local:MyControl">
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>
However, not only is this quite verbose and error-prone with several lines of redundant code (my actual project contains quite a few templated controls, not just one), I am also concerned about wasting system resources by loading the static resources several times (once for every time CommonResources.xaml is included). (Is that concern justified? Or does WPF use the same instances every time when loading a particular resource dictionary?)
So, the question is: What is the proper way to make a WPF resource accessible throughout the whole application, including control templates?
StaticResource will be resolved and assigned to the property during the loading of the XAML which occurs before the application is actually run. So, static resource has to be available at the time of loading.
It works for normal button since resource look up continues till application resources and resolve it from there. But MyControl template still not loaded into app visual tree so it can't traverse upto application resources.
There are two ways to achieve that:
Merge ResourceDictionary in Generic.xaml as well which you have already achieved.
Other way is to use DynamicResource which 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.
Read it here - StaticResource v/s DynamicResource.
This will work without merging dictionaries in Generic.xaml:
<Button Style="{DynamicResource flatButtonStyle}" Content="1"/>
<Button Style="{DynamicResource flatButtonStyle}" Content="2"/>

Reference custom resource defined in another xaml file

I am trying to create a new resource in one xaml file and reference it in another xaml file.
i.e I define
<Window.Resources>
<ImageBrush x:Key="TileBrush" TileMode="Tile" ViewportUnits="Absolute" Viewport="0 0 32 32" ImageSource="MyImageButton.png" Opacity="0.3">
</ImageBrush>
</Window.Resources>
And attempt to use it in another xaml file by
<Grid>
<Button Background="{StaticResource TileBrush}" Margin="5" Padding="5" FontWeight="Bold" FontSize="14">
A Tiled Button
</Button>
</Grid>
However I get the error "StaticResource reference 'TileBrush' was not found."
I can reference the resource from the same xaml file but don't know how to do so from another file.
In WPF, the resource references works as a tree. Each control have resource, and children control can access parent's resources. The global application resource dictionary is in the App.xaml file. In this file you can include several resource dictionaries as a Merged Dictionary. See this code sample:
<?xml version="1.0" encoding="utf-8"?>
<Application ...>
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View\SomeFileDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The SomeFileDictionary.xaml is located in the View folder of my project structure. And has looks like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:Cepha.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
... >
<DataTemplate DataType="{x:Type ViewModel:SomeType}">
<TextBox .../>
</DataTemplate>...
And each dictionary key or data template defined in this file (or App.xaml), can be referenced in any place of your project. Hope this helps...
You should define this in the app.xaml file. These resources are shared throughout the entire project

How to set tooltip for user control (from style file)

I created my control which looks like that
<UserControl BorderBrush="#A9C2DE" HorizontalAlignment="Left" x:Class="WPFDiagramDesignerControl.Components.UcWBSBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="86" Width="151" >
<UserControl.Resources>
<ResourceDictionary Source="Tooltip.xaml"/>
</UserControl.Resources>
<Grid x:Name="MainGrid">
<TextBox Name="txtBox" Style="{StaticResource DefaultStyle}" >
</TextBox>
</Grid>
I also have a file with style for tooltip "Tooltip.xaml"
How can I use this style for entire UserControl?
Usually I did this with that code
<TextBox ToolTip="{StaticResource tooltipname}"/>
But it was easy because file with style was in resource dictionary of control where I placed textbox. However I can't do sth like that
<UserControl BorderBrush="#A9C2DE" HorizontalAlignment="Left" ToolTip="{StaticResource tooltipname"}/>
Because at this point my style isn't in resource dicionary yet.
I was trying to use this syntax
<UserControl.ToolTip> </UserControl.ToolTip>
but I don't konow how should I refer to static resource
Maybe it is lame question but I just don't konow how to do it :)
One option is to just use DynamicResource instead of StaticResource to defer the lookup until runtime and then use the attribute syntax:
<UserControl ... ToolTip="{DynamicResource tooltipname}" ...
You can also write the StaticResourceExtension using element syntax so that you can write it after the Resources section:
<UserControl.Resources>
<ResourceDictionary Source="Tooltip.xaml"/>
</UserControl.Resources>
<UserControl.ToolTip>
<StaticResourceExtension ResourceKey="tooltipname"/>
</UserControl.ToolTip>

Resources