ResourceDictionary vs Resources directly under Window.Resources - wpf

Please pardon me if this was already asked, I have done a quick search to find out if it was however.
My question is what is the difference between the following two
<Window.Resources>
<ResourceDictionary>
<local:SomeClass x:Key="myobj" />
</ResourceDictionary>
</Window.Resources>
And
<Window.Resources>
<local:SomeClass x:Key="myobj" />
</Window.Resources>

They're completely equivalent. The ResourceDictionary object is implicitly assumed to be the child in the second example (MSDN calls it the "XAML implicit collection usage"). I only ever use the longer form when adding MergedDictionaries.

Related

Is it valid to use a Blend d:Style.DataContext inside WPF resource dictionary?

When defining WPF styles, I often use the Expression Blend <d:Style.DataContext> tag to let Intellisense know what the runtime DataContext will be. It works great. Unfortunately I cannot seem to make this work in a resource dictionary and I am unclear as to why.
For example, here in a style for a RadTabItem, I tell Intellisense that SettingsPageVm will be the DataContext:
<UserControl x:Class="Views.ConfigureView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:tk="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:viewModels="clr-namespace:ViewModels"
d:DataContext="{d:DesignInstance viewModels:ConfigureVm}">
<Grid>
<tk:RadTabControl ItemsSource="{Binding Categories}" >
<tk:RadTabControl.Resources>
<!-- Tell setters that SettingsPageVm will be the datacontext -->
<Style TargetType="{x:Type tk:RadTabItem}">
<d:Style.DataContext>
<x:Type Type="viewModels:SettingsPageVm" />
</d:Style.DataContext>
<!-- (Imagine many setters here, binding to SettingsPageVm) -->
This works fine.
But if try I move that same style to a separate ResourceDictionary Visual Studio complains. The editor puts a blue squiggly underneath the d:Style.DataContext declaration and highlights it red. The compiler complains about it as follows:
1>I:\Dev\MyApp\Resources\Styles\DialogStyles.xaml(13,14): error
MC4004: Style cannot contain child 'TypeExtension'. Style child must
be a Setter because it is added to the Setters collection. Line 13
Position 14.
Why is this valid in one context and not valid in another?
<ResourceDictionary 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"
xmlns:viewModels="clr-namespace:ViewModels"
xmlns:tk="http://schemas.telerik.com/2008/xaml/presentation"
>
<Style x:Key="SettingsPageTabStyle" TargetType="{x:Type tk:RadTabItem}">
<d:Style.DataContext> <!-- *** ERROR *** -->
<x:Type Type="viewModels:SettingsPageVm" />
</d:Style.DataContext>
</Style>
</ResourceDictionary>
Answering my own question because half a day later I stumbled on it.
I had neglected to add the
mc:Ignorable="d"
line to my XAML. Once I did that, everything worked fine.
(Just One of those obscure WPF lessons that I am sure I already learned and then forgot at least once before -- maybe twice -- in the past over several years of working on WPF. )

using multiple resource dictionaries

I have defined two resource dictionaries for controls which inherit from TextBox within my usercontrol like so:
<UserControl.Resources>
<ResourceDictionary Source="KeyBox.xaml" x:Key="KeyBox" ></ResourceDictionary>
<ResourceDictionary Source="kTextBox.xaml" x:Key="kTextBox" ></ResourceDictionary>
</UserControl.Resources>
I have created the styles in separate files with different target type:
<Style TargetType="b:kTextBox" >
Now when I create the controls using these resources only the style applied last actually gets applied, so if I remove the second the first works. There's something I am missing here to make use of two resources within the same usercontrol and I can't figure out what it is. Any ideas much appreciated.
Try adding your resource dictionaries like this:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="KeyBox.xaml" x:Key="KeyBox" ></ResourceDictionary>
<ResourceDictionary Source="kTextBox.xaml" x:Key="kTextBox" ></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Note that unless you have a class named kTextBox, your Style wont work.
It's also worth mentioning that your control will only have one style applied at a time, and the last resource added to the dictionary will be applied. Therefore if you have a style defined in both of your dictionaries with the same key, the one from kTextBox.xaml will be applied.

Problems adding an ObjectDataProvider in resources

I'm setting up some things in XAML, but for some reason, I'm having an issue. I'm trying to add an ObjectDataProvider to my resources, but when I'm doing that, I get this warning on my resourcedictionnary saying i cannot have multiple items in a resourcedictionnary if they don't all have key attribute in it. So I add a key to resourcedictionnary, but then I have a problem on my dynamic resource in my contentcontrol. It says it cannot resolve "DefaultEmptyPane". Then I add a reference to the key of the resourcedictionnary, but then there's some kinda of mismatch.
Is there anyone who's seeing the issue here?
Below is the XAML:
<Page.Resources>
<!--<ObjectDataProvider x:Key="projectList" MethodName=""/>-->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Panes/DefaultEmptyPane.xaml" />
</ResourceDictionary.MergedDictionaries>
<local:PopulationNameGetNameOnlyConverter x:Key="PopulationNameGetNameOnlyConverter"/>
<local:PopulationNameGetNumberOfTestsConverter x:Key="PopulationNameGetNumberOfTestsConverter"/>
<local:PopulationNameGetDateConverter x:Key="PopulationNameGetDateConverter"/>
<local:NormValidationValueToVisibilityConverter x:Key="NormValidationValueToVisibilityConverter"/>
<local:NormrequestCalculatedToVisibilityConverter x:Key="NormrequestCalculatedToVisibilityConverter"/>
<local:RemoveUnderscoreConverter x:Key="RemoveUnderscoreConverter"/>
</ResourceDictionary>
</Page.Resources>
<ContentControl Template="{DynamicResource DefaultEmptyPane}">
<!--Content-->
</ContentControl>
Jerry, the answer lies in your XAML itself. Did u observe why it gives error for ObjectDataProvider and not for RemoveUnderscoreConverter or NormrequestCalculatedToVisibilityConverter or PopulationNameGetDateConverter etc.?
Observe their placement. They are placed inside the ResourceDictionary tag butObjectDataProvider is outside it.
Hope that helps.

What is the standard convention for defining nested view:viewmodel mapping in MVVM Light

so in classic MVVM examples ive seen DataTemplate definitions are used to map up View Models to Views, what is the standard way to do this in MVVM Light framework, and where should the mappings be located? Following are examples of what I'm doing now and what I'm talking about, blendability is important to me!
Main Window:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="STS2Editor.MainWindow"
Title="{Binding ApplicationTitle, Mode=OneWay}"
DataContext="{Binding RootViewModel, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/ApplicationSkin.xaml" />
<ResourceDictionary Source="Resources/ViewMappings.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding ApplicationManagementViewModel}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
</Window>
In the above code, my RootViewModel class has an instance of the class ApplicationManagementViewModel with the same property name:
public ApplicationManagementViewModel ApplicationManagementViewModel {get {...} set {...} }
I reference the ResourceDictionary "ViewMappings.xaml" to specify how my view model is represented as a view.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:STS2Editor.ViewModel">
<DataTemplate DataType="{x:Type local:ApplicationManagementViewModel}">
<local:ApplicationManagementView/>
</DataTemplate>
</ResourceDictionary>
should I be doing things like this using ViewModelLocator? what about collections of view models?
The method you use (with implicitly typed DataTemplates) works OK in WPF, but unfortunately it does not work in Silverlight. This is one of the reason why I prefer to use a more explicit method which works in both worlds.
Also, implicitly typed DataTemplates can be a bit confusing, because it is not always quite clear where the template comes from. That can render the work of the integrator very difficult at times, especially for small changes to the UI (been there, done that :)
There is no obligation to use the ViewModelLocator in MVVM Light, it is just a way that works well and is quite easy to understand (for people reading the code who are not familiar with the subtleties of WPF/SL). In the end, it is very much a matter of preference, but lately the ViewModelLocator pattern seems to gain in popularity (see for example this post where a generic ViewModelLocator is used together with MEF).
http://www.johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum/
Finally, let me add that I am not very satisfied with the current implementation of the ViewModelLocator in MVVM Light, and I want to propose a much more generic solution in the next version.

How can I build a string resource from other string resources in WPF?

Here's my 'sample code', including what I'm trying to do. Obviously, it doesn't work at the moment, but is there any way I can make it work?
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
>
<System:String x:Key="ProductName">Foo</System:String>
<System:String x:Key="WindowTitle">{ProductName} + Main Window</System:String>
</ResourceDictionary>
The only way to add a computed string to a ResourceDictionary in this way is to create a MarkupExtension. Your MarkupExtension would be used like this:
<ResourceDictionary ...>
<sys:String x:Key="ProductName">Foo</sys:String>
<local:MyStringFormatter
x:Key="WindowTitle"
StringFormat="{0} Main Window"
Arg1="{StaticResource ProductName}" />
</ResourceDictionary>
This assumes you have created a MarkupExtension subclass in your "local" namespace named MyStringFormatterExtension that has properties named "StringFormat", "Arg1", "Arg2", etc, and has a ProvideValue() method that does the obvious.
Note that as Aran points out, a Binding using StringFormatter would be a more common way to achieve the same effect, and is generally the better design. The tradeoff is it would not allow the result to be used as part of a ResourceDictionary.

Resources