Including resource dictionary in UserControl.Resources fails to compile - wpf

I have a custom control that I want to apply some styles from a resource dictionary in another project. For some reason, adding resources in the UserControl.Resources fails, however placing it in the Grid.Resources succeeds;
<UserControl x:Class="My.Name.Space.MyUserControl"
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" d:DesignHeight="200" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary x:Key="UserControlResources">
<!--Putting it here fails-->
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.Resources>
<ResourceDictionary x:Key="GridResources">
<!--Putting it here succeeds-->
</ResourceDictionary>
</Grid.Resources>
<!--Control XAML-->
</Grid>
</UserControl>
I get an error "The name 'IntializeComponent' does not exist in the current context". However, looking at the autogenerated MyUserControl.g.i.cs file, hey presto; there it is. What am I doing wrong? What is the difference between these two declarations?
Thanks, Sterren

Related

WPF - Define a alias for a SolidColorBrush In App.Resource (StaticResourceExtension?)

I use MaterialDesign in my app and I would like to give an alias to the PrimaryHueLightBrush SolidColorBursh, which is defined there. I have found that StaticResourceExtension seems to be the solution to this. But I have not been able to get this to work.
Also I would like the "alias" to be defined in the App.xaml so the alias will be accessible from my entire application.
I have defined the "alias" in the App.xaml and I use it in the MainWindow.xaml.
App.xaml
<Application x:Class="MaterialDesignTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MaterialDesignTest"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<StaticResourceExtension x:Key="MyAlias" ResourceKey="PrimaryHueLightBrush" />
</ResourceDictionary>
</Application.Resources>
MainWindow
<Window x:Class="MaterialDesignTest.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:MaterialDesignTest"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Background="{DynamicResource MaterialDesignPaper}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
Title="MainWindow" Height="Auto" Width="500">
<Border Background="{DynamicResource MyAlias}" />
</Window
In the designer of my MainWindow I can see that the Border gets the DeepPurple color defined in the App.xaml file. So that connection seem to work.
When I try to run my application there is an error:
Index was out of range. Must be non-negative and less than the size of the collection.
VS point the error to the beginning of the x:Key parameter of the StaticResourceExtension element in the App.xaml-file.
Is there a solution for this?
I don't need to use a StaticResourceExtension. Just something so I can have an alias.
PrimaryHueLightBrush is the "alias".
What you can do is to create a copy of the brush and reference the copy instead:
<SolidColorBrush x:Key="MyAlias" Color="{Binding Color,
Source={StaticResource PrimaryHueLightBrush}}"/>

WPF Usercontrol using staticresources with Meta.Vlc

I can set vlc options in an app by adding the following to the application.xaml
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ADSNet35"
StartupUri="Start.xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Application.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="VlcOptions">
<sys:String>-I</sys:String>
<sys:String>--dummy-quiet</sys:String>
<sys:String>--ignore-config</sys:String>
<sys:String>--no-video-title</sys:String>
<sys:String>--no-sub-autodetect-file</sys:String>
</x:Array>
</Application.Resources>
</Application>
and in the xaml
<wpf:VlcPlayer xmlns:wpf="clr-namespace:Meta.Vlc.Wpf;assembly=Meta.Vlc.Wpf" x:Name="VlcPlayer1" VlcOption="{StaticResource VlcOptions}" />
and everything works great.
I have created a class library usercontrol and have used the following
UserControl x:Class="ucContainer"
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"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<x:Array x:Key="VlcOptions" Type="{x:Type sys:String}">
<sys:String>-I</sys:String>
<sys:String>--dummy-quiet</sys:String>
<sys:String>--ignore-config</sys:String>
<sys:String>--no-video-title</sys:String>
<sys:String>--no-sub-autodetect-file</sys:String>
</x:Array>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<wpf:VlcPlayer xmlns:wpf="clr-namespace:Meta.Vlc.Wpf;assembly=Meta.Vlc.Wpf" x:Name="VlcPlayer1" VlcOption="{StaticResource VlcOptions}" />
</Grid>
When the usercontrol is created I get the following error:
System.Windows.Markup.XamlParseException: 'Cannot convert the value in attribute 'VlcOption' to object of type 'System.String[]'. 'System.Windows.Markup.ArrayExtension' is not a valid value for property 'VlcOption'.
This is my first class library / usercontrol and hope someone can explain what I'm doing wrong.
I took out the <ResourceDictionary> tag and it worked fine.

Linked resource dictionary and StaticResource reference at root level

I'm aware of this, which doesn't apply to my case, and this, which I'm not sure whether it can be adapted.
I'm working on a WPF control library, and I don't have an App.xaml file. I use a file called Styles.xml to store common brushes and other resources. In the XAML file of my user control I import the resources and then I try to use brush sBrush as a background.
This works except that at the root level:
<UserControl x:Class="CMControls.TitledWindow"
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"
d:DesignHeight="300" d:DesignWidth="300"
Background="{StaticResource ResourceKey=sBrush}"> <!--EXCEPTION!-->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/CMControls;component/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Canvas Background="{StaticResource ResourceKey=sBrush}" ... <!--Ok.-->
...
I presume this happens because when the root element is instantiated its children are not, including UserControl.Resources. Is there any workaround? Note that in the designer everything works fine, no matter where I make the reference.
Change UserControl Background after Resource Merging line,because you have to add resources before using them!
<UserControl x:Class="CMControls.TitledWindow"
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"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/CMControls;component/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Background> <!--Set background here!-->
<StaticResource ResourceKey="sBrush"></StaticResource>
</UserControl.Background>
...

wpf window start up images

I would ideally like to keep the resources for a window in a resource dictionary, but am getting stuck as to the best way to make them known before you declare the window.resources section. So I wind up doing something like the code below.
Is there someway to reference the background image brush statically? How can I do better?
Cheers,
Berryl
<Window x:Class="Smack.ConstructionAdmin.Presentation.Wpf.Views.ProjectPicker.ProjectPickerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...
Background="{DynamicResource waveBrush}"
Icon="pack://application:,,,/MyAssembly;component/Images/Project_32.png"
...
>
<Window.Resources>
<ImageBrush
x:Key="waveBrush" Stretch="Fill" ImageSource="pack://application:,,,/MyAssembly;component\Images\Wave.jpg"
/>
</Window.Resources>
In your projects Application.xaml file in the Application.Resources Section.
Your could also use a standalone Resource File and include it in your windows xaml file or the Application.xaml file.
<Window x:Class="WpfApplication1.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" Background="{DynamicResource MyBackColor}">
<Window.Resources>
<ResourceDictionary Source="Resources\MyResourceDictionary.xaml" />
</Window.Resources>
<Grid>
</Grid>
</Window>
Or
<Application x:Class="WpfApplication1.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 Source="Resources\MyResourceDictionary.xaml" />
</Application.Resources>

Referencing a Parent's ResourceDictionary in a UserControl

I have a library of WPF UserControls, and a ResourceDictionary that is shared within the library.
All the UserControls in this library appear only within a single 'shell' parent control, which is really just a container for a collection of smaller controls. I'm able to access the ResourceDictionary from my shell control as expected when I add the following XAML
<Control.Resources>
<ResourceDictionary Source="MyResources.xaml" />
</Control.Resources>
However I can't access the ResourceDictionary from child controls that sit inside the 'shell' control.
I was under the impression that WPF should check locally for resources, and then traverse upwards until appropriate resources are found?
Instead I'm getting
Cannot find resource named '{BoolInverterConverter}'.
Resource names are case sensitive. Error at
object 'System.Windows.Data.Binding' in markup file...
Obviously I can (and am) referencing the ResourceDictionary in my child controls; but each and every control now needs to reference this dictionary and I believed that this was not necessary.
Any ideas, am I doing something strange or is my expectation of behaviour incorrect?
What's going on is described here, though the documentation's a little opaque. If you add a ResourceDictionary to an element'sResources property without specifying a key, WPF expects that you're merging in resource dictionaries, and it populates the dictionary with the contents of the dictionaries in its MergedDictionaries property. It ignores the actual contents of the ResourceDictionary with no key.
So what you want to do is this:
<Control.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Control.Resources>
Edit:
A working example:
MainWindow.xaml:
<Window x:Class="MergedDictionariesDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:MergedDictionariesDemo="clr-namespace:MergedDictionariesDemo" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<MergedDictionariesDemo:UserControl1 />
</Grid>
</Window>
Dictionary1.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="UCBrush"
Color="Bisque" />
</ResourceDictionary>
UserControl1.xaml:
<UserControl x:Class="MergedDictionariesDemo.UserControl1"
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"
d:DesignHeight="300" d:DesignWidth="300">
<Border Margin="10" BorderBrush="Navy" BorderThickness="1" CornerRadius="10">
<TextBlock Margin="10"
Background="{DynamicResource UCBrush}">
The background of this is set by the resource UCBrush.
</TextBlock>
</Border>
</UserControl>

Resources