How to use different UserControls(are declared in ResourceDictionary) in HeaderedItemsControl? - wpf

I have user HeaderedItemsControl to display different UserControl in my application.
Now I declared these UserControl with DataTemplate as follows in my MainWindow.
<HeaderedItemsControl.Resources>
<DataTemplate DataType="{x:Type vm:SearchViewModel}">
<vw:SearchStudentView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SearchViewModel2}">
<vw:SearchStudentView2/>
</DataTemplate>
</HeaderedItemsControl.Resources>
But I have almost 20 view and I want to place all DataTemplate in ResourceDictionary.
Can any one help me how can I use these DataTemplate's from ResourceDictionary in HeaderedItemsControl's resources?

It's very simple.
1) You must create and add DataTemplate to ResourceDictionary.
2) In App.xaml file you must add created ResoueceDictionary (TemplateResourceDictionary.xaml is my test ResourceDictionary).
<Application x:Class="ResourceDictionaryExample.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="TemplateResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
That's all. :)

Related

Cannot instantiate UserControl from another assembly - Resource cannot be found

I have a solution with two WPF projects: Primary and Secondary.
In the Primary project, a Window named PrimaryView instantiates an UserControl called SecondaryControl, defined in Secondary project.
SecondaryControl uses SecondaryStyle, which is defined in SecondaryResourceDictionary (as you might have guessed already, defined in SecondaryProject).
The fact is: when I try to run the solution, I get a XamlParseError, and digging InnerExceptions I eventually find the culprit, the ResourceNotFound error.
So my questions are:
If SecondaryControl and its SecondaryStyle are defined in the same assembly, why can't I instantiate it it PrimaryAssembly?
Should I make SecondaryStyle available to PrimaryProject namespace somehow? Why?
I try to help you by explanation how it works in my projects.
A separate assembly contains a common control and common resource dictionary like this:
CommonResources.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Some resources -->
</ResourceDictionary>
SomeCommonControl.xaml
<UserControl x:Class="YourAssembly.SomeCommonControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourAssembly;component/CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<!-- Some specific content -->
</UserControl>
I can use this control and resources from another assemblies and WPF-projects like this:
<Window x:Class="YourWPFProject.SomeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:YourAssembly">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/YourAssembly;component/CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<common:SomeCommonControl />
</Window>
I hope this will help you.

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>

Accessing resources during initialization of control

lets assume we have the following control definition
<ctrl:ChildWindow x:Class="Control.Editor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:local="clr-namespace:Control"
Width="400" Height="300"
local:AttachedProperties.DialogResult="{Binding Path=DialogResult}"
Title="{Binding Path=Caption}" Style="{StaticResource Title}" DataContext="{Binding}" HasCloseButton="False">
<ctrl:ChildWindow.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Control;component/Resources/BaseAppearance.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ctrl:ChildWindow.Resources>
</ctrl:ChildWindow&gt
The problem is that the style on the root control cannot be set because the ResourceDictionary is not loaded.
How can I get access to the StaticResource Title during the initialization of the control, when I don't have access to the App class? I'm also not sure that it would be possible, if I would have access to it.
Regards
I'd recommend accessing your resource and doing the work in the .Loaded() event of your control.
Edit: On second thought... I think I know what you're doing now... You have a resource set in your App.xaml class, but you want to access it in your control.
Easy way around the problem is to set it to a DynamicResource instead... but this is less performant.
What is the BuildAction set to on your App.xaml in the property's tab?
If it is ApplicationDefinition... then you should be able to access your resource as you currently are.
I found the common way without using code behind. I knew it is possible. ^^
<ctrl:ChildWindow x:Class="Control.Editor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:local="clr-namespace:Control"
Width="400" Height="300"
local:AttachedProperties.DialogResult="{Binding Path=DialogResult}"
Title="{Binding Path=Caption}" DataContext="{Binding}" HasCloseButton="False">
<ctrl:ChildWindow.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Control;component/Resources/BaseAppearance.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ctrl:ChildWindow.Resources>
<crtl:ChildWindow.Style>
<StaticResource ResourceKey="Title" />
</crtl:ChildWindow.Style>
</ctrl:ChildWindow&gt

Why can't I find DataTemplates in merged resource dictionaries?

In my MainWindow.xaml, I have the following reference to a ResourceDictionary:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
In MainSkin.xaml, I define a datatemplate:
<DataTemplate x:Key="TagTemplate">
...
</DataTemplate>
Deeper within my application, I attempt to use this data template:
<ContentControl DataContext="{Binding Tag}" ContentTemplate="{StaticResource TagTemplate}"/>
The code compiles successfully, but when I attempt to load a Page or UserControl that contains this StaticResource, I get an exception saying that the TagTemplate can't be found.
What am I doing wrong?
In order to access the contents of a resource defined in a XAML file, you need to "include" that XAML file in each page and control that uses it. So every XAML files will need to have the MergedDictionaries entry that you have in MainWindow.xaml.
Alternatively you can add those merge dictionaries to App.xaml and those resources are included implicitly:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Are you using that StaticResource in the same Window where it is declared? Otherwise I think that you cannot have access to that.

How to add more than one resource to a XAML window?

I have a little problem right now and I don't know how to fix it. I want to add two resources to a window. One is a XAML File style resource, the other a ValueConverter Class.
Both of them work if I use only one resource at a time:
<Window.Resources>
<ResourceDictionary Source="Resources\MyStyles.xaml" />
<Window.Resources>
or
<Window.Resources>
<local:MarginConverter x:Key="adjustMargin"/>
</Window.Resources>
But if I try something like this:
<Window.Resources>
<local:MarginConverter x:Key="adjustMargin"/>
<ResourceDictionary Source="Resources\MyStyles.xaml" />
</Window.Resources>
I get the message the resource is already been set and can not set twice.
I have no idea how to get this done. Is there something like a resource group?
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\MyStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<local:MarginConverter x:Key="adjustMargin"/>
</ResourceDictionary>
</Window.Resources>

Resources