Basing On a style defined inside a custom control library - wpf

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>

Related

XAML Restricting visibility of styles from merged ResourceDictionaries

I'm working on a WPF application, which uses styles stored in many resource dictionaries, referenced in App.xaml and I have been struggling with restricting visibility of styles used internally, to build templates of controls.
Let's say that I have a ResourceDictionary called ButtonStyles which contains the following:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonInternalStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource SomeInternalStyle}">
<!--Setters-->
</Style>
I also have a second ResourceDictionary called ButtonInternalStyles, which contains:
<Style x:Key="SomeInternalStyle" TargetType="{x:Type Button}">
<!--Setters-->
</Style>
My App.xaml references only ButtonStyles ResourceDictionary, but I can use SomeInternalStyle in my Views, which I don't want to be able to do.
Is there a way to restrict a visibility of ButtonInternalStyles, so I can use it only in ButtonStyles?
Is there a way to restrict a visibility of ButtonInternalStyles, so I can use it only in ButtonStyles?
No, I don't think you can do this. All resources defined in a ResourceDictionary that is merged into another ResourceDictionary that is indeed in scope, will also be in scope. That's how resource dictionaries work.
I don't really see the problem though. If you want to prevent a consumer of your ResourceDictionary from accidentally using your "internal" style, you might give it some name that is hard to guess, e.g.:
<Style x:Key="ffdsghdfsgh" TargetType="{x:Type Button}">
...
Of course this won't help if you use some tool for Visual Studio that provides IntelliSense support and I think you're better of not changing the names of your styles. It's not worth the effort.

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}" />

Override Control Style

I have created a CustomControlLibrary.dll, that contains a Control (MyControl), with its style in the Generic.xaml of the Themes folder, as per the default automatic setup.
If I want to include that dll in 2 different projects, each of which providing a custom style for "MyControl" to give it a different look, where do I put those custom styles?
I thought I just had to have a Themes\Generic.xaml for each application, that defines the custom style, but having done this, it still ends up using the style defined in CustomControlLibrary.dll
You have CustomControlLibrary.dll which is the owner of MyControl. Inside that dll you have your themes defined. Any other project that may contain your dll doesnt haven to have themes defined.
Other projects may define their custom style for MyControl in their window resource for example.
Styles may be defined at any level. :)
Check this link out:
http://msdn.microsoft.com/en-us/library/ms745683.aspx
Solution will be to define specific style for each project and apply it correspondingly.
But keep in mind that you can create proper style "inheritance" by using BasedOn property. After all you should get a set of styles that you'll manage in MergedDictionaries:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/CustomControlLibrary;component/styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

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

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.

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>

Resources