Using Resource Dictionaries in a Class Library - wpf

I'm using this (excellent) flowchart diagram designer in my application, but I'd like to use it as a UserControl.
To convert the Application into a UserControl I've changed the only window the application had:
<Window x:Class="DiagramDesigner.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:DiagramDesigner"
xmlns:c="clr-namespace:DiagramDesigner.Controls"
WindowStartupLocation="CenterScreen"
Title="Diagram Designer"
Height="850" Width="1000">
<Window.Resources>
<ContextMenu x:Key="DesignerCanvasContextMenu">
...
</ContextMenu>
</Window.Resources>
...
</Window>
into an user control:
<UserControl x:Class="DiagramDesigner.DiagramDesignerWPFControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:DiagramDesigner"
xmlns:c="clr-namespace:DiagramDesigner.Controls"
Height="850" Width="1000">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary.MergedDictionaries>
<ContextMenu x:Key="DesignerCanvasContextMenu">
...
</ContextMenu>
</ResourceDictionary>
</UserControl.Resources>
...
</UserControl>
I took the ResourceDicctionary from the contents of App.xaml and added it to the control. Then I deleted the App.xaml file, as it can't be used in Class Library compilations.
My problem is:
When I add that new User Control to a WPF Form in another project, I can run the new application, I can add chart components and move them, but when I join/link the following exception raises:
Cannot find resource named '{SolidBorderBrush}'. Resource names are case sensitive.
What am I doing wrong with the resources or their location in my User Control?
Edition after accepting the answer:
The risen exception also pointed to a line where the '{SolidBorderBrush}' was called. I didn't initially put it in this question, as it was a call and not a declaration. This is the piece of code which linked the exception:
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource ToolbarSelectedBackgroundBrush}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource SolidBorderBrush}" />
</Trigger>

Im guessing here, because your question doesn't actually show any of the code which seems to be causing the issue, but you probably need to use DynamicResource.
{DynamicResource SolidBorderBrush}
You can only use StaticResource under very particular circumstances. You get a big performance boost most of the time, but it's very easy to end up in a situation where it can't be used (which may be what has happened).

Related

WPF: How do I refer to an application resource textblock within any given window?

I am fairly new to WPF. I understand the concept of defining global application resources to which I can refer throughout the application. I see I can define a textblock under application resources but can't seem to see how to refer to it within a window.
In the Application.Resources I have the following code:
<TextBlock x:Key="ABC_Copyright" Background="Beige" Text="Copyright 2016 ABC Company" />
How to I construct a new textblock in any given window that refers back to the "ABC_Copyright" application resource?
Thanks in advance.
We define it as a style;
<Style x:Key="ABC_Copyright" TargetType="TextBlock">
<Setter Property="Background" Value="Beige"/>
<Setter Property="Text" Value="Copyright 2016 ABC Company"/>
</Style>
Then we use it at whatever instance we need to;
<TextBlock Style="{StaticResource ABC_Copyright}"/>
Hope this helps, cheers.
Create a ResourceDictionary where you want to store and just put your your Resource Dictionary name as the source of ResourceDictionary in the App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Your Resource Dictionary Name"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Now in ResourceDictionarystyle your textbolckthat can be accessible from any other palces like that,
<Style x:Key="TxtStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Text" Value="Copyright 2016 ABC Company"/>
</Style>
Now refer your textblock to the styled textblock
<TextBlock x:Key="ABC_Copyright" Background="Beige" Style="{StaticResource TxtStyle}"/>

Defining WPF Window style in class library

Currently I am developing some WPF class library, which will have several WPF Windows and trying to create my own window ControlTemplate for these Windows to make more nice design of these windows (inspired by this article: Reusing Control Templates in Resource Dictionaries).
Problem is, then it's a WPF class library not an application assembly, where i can use app.xaml and to define my resource dictionary reference & etc...
Using code below i getting an error: StaticResource reference 'MyWindowStyle' was not found
<Window x:Class="SomeERP.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Style="{StaticResource MyWindowStyle}">
<Window.Resources>
<!-- My Window Style -->
<Style x:Key="MyWindowStyle" TargetType="Window">
<Setter Property="Background" Value="Transparent" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Opacity" Value="0.95" />
<Setter Property="Template" Value="{StaticResource MyWindowTemplate}" />
</Style>
<!-- Window Template -->
<ControlTemplate x:Key="MyWindowTemplate" TargetType="{x:Type Window}">
<Grid>
</Grid>
</ControlTemplate>
</Window.Resources>
</Window>
I suspect i get this error because in my case it's not predeclared before Window declaration as in application's case in app.xaml which i don't have in class libary. I am pretty new in WPF and just starting to use WPF design possibilities.
If you need the style only once, the solution is pretty simple: Just define the style in-place
<Window.Style>
<!-- My Window Style -->
<Style TargetType="Window">
...
</Style>
</Window.Style>
However, if you need the style in more than one window, it is reasonable to define the style in a resource dictionary. Then you can integrate the resource dictionary in the window's resources and set the style accordingly:
<Window.Resources>
<!-- My Window Style -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
<!-- path to the resource dictionary -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resource>
<Window.Style>
<StaticResource ResourceKey="MyWindowStyle"/>
</Window.Style>
Looks like i've found solution to my problem in this post: Assembly-wide / root-level styles in WPF class library and according to this post What's the difference between StaticResource and DynamicResource in WPF?
A StaticResource will be resolved and assigned to the property during the loading of the XAML which occurs before the application is actually run. It will only be assigned once and any changes to resource dictionary ignored.
A DynamicResource assigns an Expression object to the property during loading but does not actually lookup the resource until runtime when the Expression object is asked for the value. This defers looking up the resource until it is needed at runtime. A good example would be a forward reference to a resource defined later on in the XAML. Another example is a resource that will not even exist until runtime. It will update the target if the source resource dictionary is changed.
That was what i needed, as i have class library, i don't have app.xaml and can't predeclare resources for Window. I just need to use DynamicResource rather than StaticResource to get it working.
Thanks for attention :)
Just add the external assembly:
<Application.Resources>
<ResourceDictionary>
Source="/MyAssemblyName;component/MyResources.xaml"
</ResourceDictionary>
</Application.Resources>

DynamicResource Cannot be resolved

I have been trying to learn about resources and styles, I want to create a chromeless window.
I have an example that acheives what I want via the following simple extracts of xaml.
I have a Resource set in Themes/Generic.xaml
<Style x:Key="BorderlessWindowStyle" TargetType="{x:Type Window}">
<Setter Property="AllowsTransparency" Value="true" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanResizeWithGrip" />
<Setter Property="Background" Value="Transparent" />
</Style>
I have a main window:
<Window x:Class="Project1.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Project1"
x:Name="Window"
Title="Shell" Height="576" Width="1024" Style="{DynamicResource BorderlessWindowStyle}">
<Grid></Grid>
But the style is not being applied and VS designer states it cannot resolve the resource.
The example I have been looking at does things this way and I cannot discover the difference between what I have seen done and what I am trying to do.
I thought that Genric.xaml was a 'special' resource dictionary that should be discoverable by my Window control - and I am guessing this assumption is my error.
What do I need to do to make this work? (Now I understand I can set these properties in the Window xaml directly, and I have done so and get the effect I want. BUT I really want to undersatnd using the Generic.xaml resource dictionary way as I have presented here)
best regards
John.
Themes/generic.xaml file is automatically used to find default styles for Custom Controls. In your case you have an ordinary Window with custom style. You cannot define this style in Window.Resources section, because the style should be defined at a higher level. The only higher level of Window is App.xaml, because the Window is in fact its child. That's why the solution for your question is to place the style into App.Resources section.
Thought I would add the following example in case it helps some others out. To add a resource dictionary to your app.xaml file you can add the following xaml code to the app.xaml file.
<Application x:Class="ProjectX.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProjectX"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Use the Black skin by default -->
<ResourceDictionary Source="Resources\ResourceFile.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Where 'Resources' coudl be a folder in your project that contains the Resource Dictionary file (ResourceFile.xaml).
The you can add code to your resource dictionary like such:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProjectX.Resources">
<!-- The Background Brush is used as the background for the Main Window -->
<SolidColorBrush x:Key="MainBackgroundBrush" Color="#FF202020" />
</ResourceDictionary>
And then finally, dynamically bind to your resource dictionary doing something like:
<Window
x:Class="ProjectX.MainWindow"
Title="Family.Show" Height="728" Width="960"
Background="{DynamicResource MainBackgroundBrush}"
ResizeMode="CanResizeWithGrip">
</Window>

WPF: Style ListBoxItem to unify colors

I am starting with WPF development on a touch device. Although .NET and WPF seem to be an amazing technology, I am somewhat lost.
I am developing a generic control. I defined an UserControl which contains a Grid, some buttons and a SurfaceListBox. In the actual C#-code I am handling events and add new elements to the list box by manipulation the listItems-Attribute. This works fine so far.
Now I would like to change the style of the list items - I would like to make their background transparent if they are not selected, and completely white if they are. Unfortunately the following piece of code simply does not work. It just sets the background color of the list item text to white, but not the whole item.
Update: Now it works!
<UserControl x:Class="SGEditor.MyControl"
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"
xmlns:my="http://schemas.microsoft.com/surface/2008" UseLayoutRounding="True">
<UserControl.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<my:SurfaceListBox Width="300" Height="300" />
</Grid>
</UserControl>
Thank you!
Hans
I don't know exactly how to do what you want to do, but I'm pretty sure you can't reassign a static system value like you're trying to do in x:Key. That's just a name you use to reference the resource later in the xaml, like MyBackgroundColor or whatever.
I think what you need to do is something with triggers in the style for your control that set the appropriate properties for the elements you want to change. Hopefully someone else will shed more light on that, since I rarely do that fancy stuff. =)

XAML styles in Silverlight not being recognized

I am attempting to create a Syles.xaml file for my test Silverlight app. Here is what I have in the App.xaml file:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
x:Class="MVCSilverlight.App"
>
<Application.Resources>
<Style x:Key="NavigationContainerStyle" TargetType="StackPanel">
<Setter Property="Background" Value="Black" />
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="Height" Value="50" />
<Setter Property="Width" Value="500" />
</Style>
</Application.Resources>
</Application>
The problem is that when I include this in the app, VS2010 does not recognize it AND when I run the application, it does not display because there are errors with attempting to find that resource name/value. Here is an example of how it is being used:
<StackPanel Style="{StaticResource NavigationContainerStyle}">
</StackPanel>
I also attempting to put the styles in a file and include it in the app.xaml but that didnt work either.
Can someone give me some ideas as to why this is happening?
That XAML looks like it should work fine as long as App is still set as the startup object in the project settings and InitializeComponent() is still being called in App.xaml.cs.
If you are putting styles in a Styles.xaml file you will need use a merged resource dictionary to merge it into either the App resources or directly into the resources of the UserControl where you are going to use it.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Resources