XAML Restricting visibility of styles from merged ResourceDictionaries - wpf

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.

Related

Provide both a global theme and enforce default styles on some controls

I've applied the MaterialDesignInXamlToolkit theme to our application in the App.xaml. Using this mechanism to style the application's menu and dialogs works well, but our application also allows the user to create their own forms and customize properties for many of the WPF controls.
I need to ensure that that the global styles don't apply to any of these user-customized controls. There are only two UserControl elements in the application that may be composed of user-customized controls. To cancel the global theme I'm providing a resource dictionary of default styles in the UserControl.Resource section like so:
UserCustomizableForm.xaml
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../DefaultWPFSyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Where DefaultWPFStyles.xaml is just a list of default styles for any control that we allow the user to customize:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Style TargetType="Border"/>
<Style TargetType="Button"/>
<Style TargetType="Canvas"/>
<Style TargetType="CheckBox"/>
<Style TargetType="ComboBox"/>
<Style TargetType="ComboBoxItem"/>
...
</ResourceDictionary>
I haven't devised another way to force all controls below a designated UserConrol to default styles carte-blanche. I'm hoping someone could suggest a way if I've overlooked it.

Unable to reference BrushResource in linked ResourceProject from Style ResourceDictionary

I have a project in my application where I keep all of my Resources & reusable custom control classes (including styles, brushes, custom controls, etc.).
The App.xaml file of my Application's "Main" project references the ResourceLibrary file that references all my organized ResourceDictionary files like so:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ControlResources;component/ResourceDictionaries/ResourceLibrary.xaml"/>
<ResourceDictionary Source="Simple Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Window}">
<Setter Property="FontFamily" Value="Segoe UI" />
</Style>
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</Application.Resources>
Note: I am following this article here that includes a big-fix (the Rectangle style included above).
Below is a snapshot of what my "ControlResources" project looks like.
Referencing the style and customControl resources works great when I reference them from my main project, "GlenwareMaster", but when referencing the brush resources under "Brushes" from any of the style resources, the application is clearly not finding them.
My question: Can I just add a project-self-referencing link (an inherent right-click blend feature?). How can I get the style ResourceDictionaries to locate the Brush ResourceDictionaries in the same project?
Thanks in advance!
How are you referencing the brush resource dictionaries in your style dictionaries? Make sure you're using pack URIs and that they are correct.
My standard practice is to use the absolute pack uri format in any resource dictionaries that I plan to reference within another resource dictionary- leads to less errors if you end up moving it to another project in the future. When you reference brushes in your common style resource dictionaries, Try something like:
<ResourceDictionary Source="pack://application:,,,/ControlResources;component/ResourceDictionaries/Brushes/MyBrushes.xaml"/>
You can read more about Pack URIs here: http://msdn.microsoft.com/en-us/library/aa970069.aspx

Apply a style to multiple controls without using a key

In .NET WPF, I have the following XAML code:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="5" />
</Style>
</StackPanel.Resources>
<CheckBox>Check 1</CheckBox>
<TextBox>Some text...</TextBox>
</StackPanel>
The controls do not have any margins applied to them.
Is it possible to apply a style to multiple controls (of different types) without using a key to set the style explicitly on each control?
Styles are not inherited, you can base the subclasses' styles on that one though using BasedOn.
Another method in this case should be using an ItemsControl with an ItemContainerStyle set to this style.
There are examples for both methods in this answer.
Sorry, I misread the question before I wrote this out. My answer is useful if you want to style multiple checkboxes within the StackPanel.
Implicitly style the entire application by placing this into your app.xaml's merged dictionaries.
<Style TargetType="CheckBox" BasedOn="{DynamicResource YourBaseStyle}"/>
This also works on a much smaller scope. Reducing the scope to just that StackPanel simply requires that you add that same line of code to your StackPanel.Resources tag.

WPF Grid.Resources Style breaks ResourceDictionary Style. How to make them coexist?

In a WPF app I have a ResourceDictionary with Style defined for the TargetType MyCustomControl:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:MyControlLibrary;assembly=MyControlLibrary" >
<Style TargetType="{x:Type cc:MyCustomControl}">
<Setter Property="Prop1" Value="1" />
<Setter Property="Prop2" Value="2" />
...
The problem is that I need to define a context menu for MyCustomControl in the page XAML like following:
<Grid>
<Grid.Resources>
<ContextMenu x:Key="MyControlContextMenu">
<MenuItem Name="Name1"
Header="Header1"
Click="Cm1_Click"
.../>
....
</ContextMenu>
<Style TargetType="{x:Type ScNamespace:MyCustomControl}">
<Setter Property="ContextMenu" Value="{StaticResource MyControlContextMenu}"/>
</Style>
</Grid.Resources>
...
In this case, though I only assign one Property in the Style definition inside my Grid, the ResourceDictionary Style values are not applied at all. They get overridden by page resource style and ignored.
How to solve this issue? Maybe there is a way to make a reference to ResourceDictionary in the Grid.Resources section to enforce looking up the ResourceDictionary Style?
Base your new style on your default style:
<Style TargetType="{x:Type ScNamespace:MyCustomControl}" BasedOn="{StaticResource {x:Type ScNamespace:MyCustomControl}}">
<Setter Property="ContextMenu" Value="{StaticResource MyControlContextMenu}"/>
</Style>
Not sure if it is what you're looking for, but a Style can inherit from another. With the BasedOn-property you can define the base style of a Style, so that the new style inherits all settings from this style.
However I never tried if it works also if the BasedOn references to the same key (type). Maybe it works:
<Style TargetType="{x:Type ScNamespace:MyCustomControl}"
BasedOn="{x:Type ScNamespace:MyCustomControl}">
If this works not, maybe you can separate the Style, define it globaly with a key and then reference to the globaly defined Style via the BasedOn-property.
In general, Controls should have their default Styles defined in the Themes folder in a theme specific file (see here for more info).
When an application looks for a
resource, it looks at three levels in
the following order:
1) The element level.
The system starts with the element
that references the resource and then
searches resources of the logical
parent and so forth until the root
element is reached.
2) The application level.
Resources defined by the Application
object.
3) The theme level.
Theme-level dictionaries are stored in
a subfolder named Themes. The files in
the Themes folder correspond to
themes. For example, you might have
Aero.NormalColor.xaml,
Luna.NormalColor.xaml,
Royale.NormalColor.xaml, and so on.
You can also have a file named
generic.xaml. When the system looks
for a resource at the themes level, it
first looks for it in the
theme-specific file and then looks for
it in generic.xaml.
In your case, you have two implicit Styles, so HCL and Kent's answers should work. Since only one implicit Style can be applied at a time. Same goes for setting the Style properly directly. In that case, no implicit Styles will be applied.
If you have your first Style setup as a default Style at the theme level, then it would be applied in addition to your second implicit Style (or any explicitly defined Style).

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