How can data templates in generic.xaml get applied automatically (redux)? - wpf

This is a follow-up to a question posted by Thiado de Arruda. In short, he wanted to have a DataTemplate in his generic.xaml file, but the template wasn't being applied.
The answer given suggested placing the DataTemplate in the ControlTemplate.Resources for the control that hosted his custom type. This works very well, however, suppose that he needed the DataTemplate to apply in other places, not just within the host control. Would it be necessary to copy the DataTemplate to the ControlTemplates of every other host control?
Edit (restating question):
I am developing a WPF application using MVVM design principles. MainWindow.xaml contains the structure of the UI, and all of the styling is coded in Themes\generic.xaml. (The behavior is coded in a separate view model class, but that's irrelevant.) As part of the UI, I created a subclass of ListBox (MyListBoxSubClass) to display a collection of an ordinary .Net object of my own creation (MyObject). MyListBoxSubClass has a style in generic.xaml that redefines the Template property, and it gets applied as expected. I also have a DataTemplate for MyObject in generic.xaml, but this does not get applied. According to the above link, I have to place the DataTemplate in the Resources collection of the ControlTemplate for MyListBoxSubClass in order for this DataTemplate to be applied. This works wonderfully.
My question is how to get the DataTemplate to apply to MyObject everywhere in my application without having to duplicate the DataTemplate? I've tried adding a key to the DataTemplate and referencing it where I need it, but for some reason, I get a XAML parse error at runtime, and Resharper says that it can't resolve my DataTemplate key.

Add the data template in a separate resource dictionary in another XAML file.
Bring the XAML file into your generic.xaml control template resources:
<ControlTemplate ...>
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
</ControlTemplate>
Then wherever else you want to use this data template, you can bring it into merged dictionary of resources of wherever you want - user control, window, another control template, etc...
<Window x:Name="someWindow">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</Window>
Hope this helps.

Related

How to make a globally available style WITHOUT App.xaml

I have a class library I am creating for an AutoCAD plugin that includes WPF control elements. I would like to add a theme to these elements, so I added the WPFThemes.DarkBlend package from Nuget.
To property utilize the theme, you are supposed to add the style reference to your App.xaml file like so:
<Application
...
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes\Styles.xaml” />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Now unfortunately, because this is only a class library, I do not have an App.xaml file in which to add this code. I am able to use my Window.Resources, but in doing so, I am afraid that the styles in the reference are not exposed to the Window element. Is this because the Window is not within the scope of its own resources? Below is an image that shows my current situation:
Thank you!
After creating an x:Key in the style called "DarkWindow", I found that I was able to apply the style directly in the PluginWindow.xaml window properties like this:
<Window Style="{DynamicResource DarkWindow}" />

Use Resource Dictionary Styles in my class library project without merging dictionaries

I am creating a class library project that will contain WPF user controls. My Requirement is that all controls have the same style. My project looks like:
Things I have done in order to solve this problem:
Added all references needed by a WPF application System.Xaml, WindowsBase, etc.. so that I can have wpf controls in my class library project.
In AssemblyInfo.cs I have added:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Added ResourceDictionary1.xaml To the project adding the style.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="Brush1" Color="#FF19199E"/>
</ResourceDictionary>
Now if I want to use a style on my UserControl1.xaml I do:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid >
<Rectangle Fill="{StaticResource Brush1}" />
</Grid>
I know it works great but here is the catch. Every time I create a new userControl I will have to merge the dictionary. On a regular WPF application I could just merge the dictionary once on App.xaml and I will be able to use that dictionary on my entire application. How can I avoid having to merge the dictionary every time I create a new userControl? If I plan on addying a new resource dictionary I will have to go to all userControls and merge another dictionary. Perhaps I wrote the question title incorrectly and my question should have been how can I add a App.xaml file to a class library project
You should replace the source value ResourceDictionary1.xaml like the follow:
Source="pack://application:,,,/ControlsDLL;component/ResourceDictionary1.xaml">
or just simple as following:
<UserControl.Resources>
<ResourceDictionary Source="pack://application:,,,/ControlsDLL;component/ResourceDictionary1.xaml"></ResourceDictionary>
</UserControl.Resources>

WPF Resources - the property can have only one child element if it uses an explicit collection tag

I am trying to add a resource dictionary to a user control as follows:
User Control View/AllOrdersView.xaml
Resource Dictionary View/AllOrdersViewResources.xaml
Solution Explorer Showing the UserControl and ResourceDictionary
Error Message
Cannot add element to property 'Resources', because the property can
have only one child element if it uses an explicit collection tag.
Troubleshooting Steps
Ensure the build action of AllOrderViewResource.xaml is "page" as suggested in this question: Cannot find resource dictionary in WPF application
Your XAML is wrong. This is the right way to merge ResourceDictionaries:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AllOrdersViewResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- More resources here -->
</ResourceDictionary>
</UserControl.Resources>

Can I merge a resource XAML dictionary in a single page's resources?

My application has a single page with an explicit dark background (dark image), but the rest of the application uses the system colors. Is there a way to use the merged dictionary technique outlined here, but only for a single page, in order to not have to explicitly set the colors (and styles for TextBox controls, etc) on each control one by one?
Thanks.
The technique you have linked to is not limited to the App.xaml. It can be used in any definition of a ResourceDictionary. Everywhere you see a Resources property an implicit ResourceDictionary is created for you when it is accessed. However in all these places you can also explicitly define one. This will allow you to also manipulate its MergedDictionaries property.
<Grid x:Name="LayoutRoot">
<Grid.Resources>
<ResourceDictionary>
<ResourceDicitonary.MergedDictionaries>
<ResourceDictionary Source="urlToAnotherXamlFile" />
</ResourceDicitonary.MergedDictionaries>
</ResourceDictionary>
</Grid.Resources>
.... Content ....
</Grid>

Basing On a style defined inside a custom control library

I'm extending the available WPF's TreeView control.
I wish to add to it CheckBox behavior like Josh Smith has suggested.
My goal is to encapsulate all checkbox behavior concerns from the end user (which is a different approach of what Josh Smith has done).
I would like to use a style for the TreeViewItem in order to add some properties and bindings as described in the article.
So I have created a style, pushed him to the generic.xaml and called it TreeViewItemStyle.
My requirement is that I still wish that the end user can add a style (for colors and theme) on his own.
One way to do that is using the BaseOn property of the style, but it must use StaticResource and it fails to find my style, TreeViewItemStyle.
Is there a workaround? Is it actually a good approach?
What do you do?
Ariel
Did you include the generic.xaml file in the new resource dictionary you are trying to create?
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ASSEMBLY;component/Resources/generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="NewStyle" BasedOn="{StaticResource TreeViewItemStyle}">
</Style>
</ResourceDictionary>

Resources