How can I reference a resource in a separate ResourceDictionary in WPF? - wpf

In my project (ABC), I have MainWindow.xaml where I have defined a toolbar for it and this toolbar is defined in
project under Resource/Views/ApplicationToolbar.xmal as following:
I have referenced it in my MainWindow.xaml as xmlns:local="clr-namespace:ABC" and as soon as I run it I get an
error indicating View123 not found.
More information: (EDIT)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ABC">
<StackPanel x:Key="View1">
<Button Margin="3" Content="Test1"></Button>
<Button Margin="3" Content="Test2"></Button>
</StackPanel>
</ResourceDictionary>
Now in MainWindow.xmal have:
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ABC"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<!-- FOLLOWING LINE CAUSING ERROR-->
<ContentControl Name="Toolbar" Content="{StaticResource View1 }"></ContentControl>
</Grid>
</Window>
What am I missing?
Thanks,
Amit

Since View1 is referenced in a separate ResourceDictionary you need to merge it into the ResourceDictionary for this Window.
Try adding this to the code just inside your Window declaration:
<Window.Resources>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resource/Views/ApplicationToolbar.xaml"/>
</ResourceDictionary.MergedDictionaries>
</Window.Resources>
At this point your Window should be able to reference View1.
Note: I haven't tested this fully in an IDE, so it's possible there could be a slight syntax error or issue with the path. You may have to format your dictionary URL with a Pack URI in order for the reference to resolve correctly. Resource paths in WPF tend to be a little tricky.

Thanks to all. OK, I tried what was suggested here and I appreciate Mike and it was close to the solution. What worked for me was adding following tag in App.xaml:
<Application.Resources>
<ResourceDictionary Source="Resources/views/ApplicationToolbar.xaml"/>
</Application.Resources>
Thanks.
Amit

Related

WPF: Similar xaml

So i have some similar windows and their xamls are the same. Obviously duplicated code is not good. And i would like my windows shared xaml from only file. I created DataTepmlate containing common xaml and placed it into ResourceDictionary. But i don't know how to place DataTemplate from resource dictionary into xaml file.
my datatemplate:
<UserControl x:Class="PeriodicTable.View.CollectionViews.CollectionTemplate"
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">
<Grid>
<ListBox Name="Lst" ItemsSource="{Binding Entity}"
HorizontalContentAlignment="Stretch"
Grid.IsSharedSizeScope="True" >
<!-- lots and lots of code -->
</ListBox>
</Grid>
</UserControl>
my Resources.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:collectionViews="clr-namespace:PeriodicTable.View.CollectionViews"
xmlns:collectionViewModels="clr-namespace:PeriodicTable.ViewModel.ViewModel.CollectionViewModels">
<DataTemplate x:Key="ComonCollectionTemplate" DataType="{x:Type collectionViewModels:PeriodsCollectionViewModel}" >
<collectionViews:CollectionTemplate />
</DataTemplate>
</ResourceDictionary>
File where i would like to put my datatemplate:
<Window x:Class="PeriodicTable.View.CollectionViews.PeriodCollectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PeriodWindow" Height="350" Width="750" >
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
what i should write here to place my DataTemplate from Resources.xaml?
</Window>
Use ContentControl and set its ContentTemplate to the resource declared in resource file.
<ContentControl ContentTemplate="{StaticResource ComonCollectionTemplate}"/>

Using one class library (and theme) as basis to another class library

Still learning this stuff on WPF, themes, derivations, etc.
I understand basics on the "Themes\Generic.xaml", and then setting your application's app.xaml file to include the resource dictionary pointing to the theme in question.
So, thats fine from an application project perspective. Now, how about from a class library/dll file. I have a DLL project which I want to use as the basis of all controls in my project. In that, I have the Themes/Generic.xaml and have it coded up with some basics to confirm visual design implementation (originally confirmed ok, when tested under an App/exe project).
Now, I want this theme at a level BEFORE the actual application. Again, this is the baseline. Now, I add a second library of custom grouped controls (for example, a user control for address information... multiple address lines, city, state, zip, labels, etc). I want this second library to reference the first library with the themes, so I can see visually at design time what it will look like (alignments, colors, fonts, etc).
What / where should I be looking to let one DLL know about the merge dictionaries that are the basis in the first DLL. Hope this makes sense.
-- EDIT -- for clarification
First Class Library... "MyThemeLibrary" compiles into a .dll
In this dll is path/file of "/Themes/MyTheme.xaml"
As suggested by first answer, if I have a Resource Dictionary in the first library, I can reference it in anything else that I will derive from it. So, I have
<ResourceDictionary x:Name="MyGenericTheme"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/MyTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Second Class Library... "SecondLevel" compiles into a .dll
In this, I have a user control that I want to put a grid for columns/rows, labels and textbox controls into. I want the controls to respect the colors, fonts, sizes, alignments as defined in the "MyTheme.xaml" of the first dll.
<UserControl x:Class="SecondLevel.multipleControlContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Something"
Grid.Row="0" Grid.Column="0" />
<TextBox Text="Testing" Grid.Row="1" Grid.Column="1" />
</Grid>
</UserControl>
So, how / what should I do the necessary reference, declaration, inclusion of resource dictionary from the first library into the second.
make a reference to your dll and if you know where your theme is located you can do this one
<Application x:Class="My.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Common base theme -->
<ResourceDictionary Source="pack://application:,,,/Your.Base.Dll;component/YourResDictionary/YourTheme.xaml" />
<!-- here comes your custom theme -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
do this in the App.xaml
EDIT after clarification (look at the comments)
<UserControl x:Class="SecondLevel.multipleControlContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Common base theme -->
<ResourceDictionary Source="pack://application:,,,/Your.Base.Dll;component/YourResDictionaryFolder/MyGenericTheme.xaml" />
<!-- Custom theme -->
<ResourceDictionary Source="pack://application:,,,/Another.Dll;component/AnotherResDictionaryFolder/MyCustomTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<!-- all controls in this usercontrol respect the styles in MyGenericTheme.xaml"
if you use implicite styles-->
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Something"
Grid.Row="0"
Grid.Column="0" />
<TextBox Text="Testing"
Grid.Row="1"
Grid.Column="1" />
<!-- if you use explicit styles then you must do this -->
<TextBox Style="{StaticResource myTextBoxStyle}"
Text="Testing"
Grid.Row="1"
Grid.Column="1" />
</Grid>
</UserControl>

How can I display my user control in the MainWindow?

I'm trying to build a small MVVM test application, but can't really figure how to display my user control in the MainWindow.
My Solution Explorer:
I got a resource dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
xmlns:vw="clr-namespace:MVVM.View">
<DataTemplate DataType="{x:Type vm:ViewModel}">
<vw:View />
</DataTemplate>
</ResourceDictionary>
I got my view:
<UserControl x:Class="MVVM.View.View"
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">
<UserControl.Resources>
<DataTemplate x:Key="PersonTemplate">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<ListBox ItemsSource="{Binding Path=Persons}"
ItemTemplate="{StaticResource PersonTemplate}" />
</UserControl>
and My MainWindow
<Window x:Class="MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<Grid>
</Grid>
</Window>
The most obvious and easiest way is to add the ContentControl element:
<Grid>
<ContentControl x:Name="mainContentControl" />
</Grid>
And after that set the Content property of this control to your view model, and the corresponding view will be loaded and applied automatically:
this.mainContentControl.Content = new ViewModel.ViewModel();
But I would prefer to use another way without datatemplates:
<Grid>
<vw:View x:Name="mainView"/>
</Grid>
this.mainView.DataContext = new ViewModel.ViewModel();
Build your VS2010 solution, then, go to your MainWindow's XAML.
On the left, there is a toolbar with button "Toolbox"
Open it, it contains all the possible WPF controls you could add to your UI
Your UserControl should appear on top of the list (in a category probably named "MVVM Controls"), just drag&drop it to your UI :)

Set Style for user control

I am trying to set a style for my user control. The UserControl is in a project "Controls" and the theme is in a project "MainProject"
<UserControl x:Class="Controls.OutputPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="OutputControl">
<!-- Style="{DynamicResource UserControlStyle}"> - I cant set the style here because the Resource Dictionary hasn't been defined yet -->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MainProject;component/Themes/MyTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<!-- Now that the Resource Dictionary has been defined I need to set the style -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="textbox"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Text="{Binding ElementName=OutputControl, Path=TextProperty}"
IsReadOnly="True"
Style="{DynamicResource OutputTextBoxStyle}"/>
</Grid>
</UserControl>
That should be working fine as far as I can see. Do you get any special warnings or errors or do some parts from the Style not get applied?
To set the Style after Resources has been set, you can use the following syntax
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MainProject;component/Themes/MyTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Style>
<DynamicResource ResourceKey="UserControlStyle"/>
</UserControl.Style>
If you're still having problems after this you can compare it to my sample app which I uploaded here: http://www.mediafire.com/?q1v98huubzw02zb
You could make new resource dictionary, define your style there and than add it in app resources.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UC="clr-namespace:UserControls;assembly=UserControls">
<Grid>
<UC:myUserControl/>
</Grid>
</Window>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UC="clr-namespace:UserControls;assembly=UserControls">
<Style TargetType="UC:myUserControl">
...
</Style>
</ResourceDictionary>
And

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>

Resources