Problems adding an ObjectDataProvider in resources - wpf

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.

Related

ResourceDictionary makes use of UserControl -> Resources within UserControl cannot be resolved

I have Resources defined as a ResourceDictionary in App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AssemblyName;component/Resources/HamburgerMenuStyles.xaml" />
<!--…-->
</ResourceDictionary.MergedDictionaries>
<converters:LanguageConverter x:Key="LanguageConverter"/>
<!--…-->
</ResourceDictionary>
</Application.Resources>
Then, in the ResourceDictionary "HamburgerMenuStyles.xaml" that is included in above code I make use of a UserControl:
<mah:HamburgerMenu.OptionsItemsSource>
<mah:HamburgerMenuItemCollection>
<mah:HamburgerMenuIconItem Label="{localization:Loc tabConf}">
<mah:HamburgerMenuIconItem.Icon>
<!--…-->
</mah:HamburgerMenuIconItem.Icon>
<mah:HamburgerMenuIconItem.Tag>
<controls:Settings/> <!--Calling the UserControl here-->
</mah:HamburgerMenuIconItem.Tag>
</mah:HamburgerMenuIconItem>
</mah:HamburgerMenuItemCollection>
</mah:HamburgerMenu.OptionsItemsSource>
I get errors, that resources used within the UserControl (the resources used there are also placed in App.xaml) cannot be resolved, eventhough the code compiles and works. How come? I do not get intellisense errors in the UserControl.xaml itsself.
Example:
Visual Studio complains about a converter used in the UserControl which is defined as a resource in App.xaml and does not show any errors in the control xaml + compiles and works.
Adding the "missing" resource to the control, compiling and then removing the resource again resolved my problem:
<mah:HamburgerMenu.OptionsItemsSource>
<mah:HamburgerMenuItemCollection>
<mah:HamburgerMenuIconItem Label="{localization:Loc tabConf}">
<mah:HamburgerMenuIconItem.Icon>
<!--…-->
</mah:HamburgerMenuIconItem.Icon>
<mah:HamburgerMenuIconItem.Tag>
<controls:Settings>
<controls:Settings.Resources>
<converters1:InvertBoolConverter x:Key="InvertedBoolConverter"/>
</controls:Settings.Resources>
</controls:Settings>
</mah:HamburgerMenuIconItem.Tag>
</mah:HamburgerMenuIconItem>
</mah:HamburgerMenuItemCollection>
</mah:HamburgerMenu.OptionsItemsSource>
This seems to have been a bug somehow. No problems remaining :-)

ResourceDictionary vs Resources directly under Window.Resources

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.

WPF how to reference application resource from merged dictionary?

So if I have a converter in the resource dictionary for my app like so:
<Application.Resources>
<ResourceDictionary>
<Converters:ColorToBrushConverter x:Key="ColorToBrushConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionaries/GraphViewerBrushes.xaml" />
<ResourceDictionary Source="ResourceDictionaries/ColorPickerResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
How can I reference the converter from within one of the external xaml files? or is this not possible? i know i could just reinstance another converter there, but that seems wasteful.
You can use DynamicResource instead of StaticResource to reference the converter. This will cause it to look up the resource dynamically, which should succeed as it's part of the Application resources.
That being said, I typically just create another instance, as it is simpler, and a converter has very, very little overhead to create (since it should have no state).

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.

Trouble referencing a Resource Dictionary that contains a Merged Dictionary

I have a library, CommonLibraryWpfThemes, with several Resource Dictionary XAML files in it. My Themes/Generic.xml file contains a ResourceDictionary.MergedDictionaries declaration that merges all the other files together.
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
In my application project, I have a reference to CommonLibraryWpfThemes, and I explicitly reference Generic.xml in my App.xaml file.
App.xaml -- FAILS
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</Application.Resources>
</Application>
This doesn't work. I get the following error when I run my app:
System.Windows.Markup.XamlParseException occurred
Message="Cannot find resource named '{_fadedOrangeBrush}'. Resource names are case sensitive. Error at object 'System.Windows.Setter' in markup file 'CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml' Line 18 Position 13."
Source="PresentationFramework"
LineNumber=18
LinePosition=13
If I place the contents of Generic.xaml into App.xaml directly, everything works fine:
App.xaml -- SUCCEEDS
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Maybe I'm going about this in the wrong way. My goal is to make it easy to reference all my theme resources from multiple applications without having to list out all the individual files. Is there a recommended way to do this? (Note: I'm not trying to switch between multiple themes--I just have one theme.)
As a bonus, it would be nice if someone could tell me how to reference resources in an external library without breaking the designer in Visual Studio.
Thanks.
EDIT:
I tried wrapping the ResourceDictionary in a ResourceDictionary.MergedDictionary element, but that also didn't work (I get the same error):
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Answered a similar question here earlier, see Adding a Merged Dictionary to a Merged Dictionary question.
This is an optimization bug, see Microsoft Connect / DefaultStyleKey style not found in inner MergedDictionaries:
On the creation of every object in
XAML, if a default style is present
(i.e. style w/ a key of Type) that
style should be applied. As you can
imagine there are several performance
optimizations to make that (implied)
lookup a light weight as possible. One
of them is that we don’t look inside
Resource Dictionaries unless they are
flagged as “containing default
Styles”. There is a bug: if all your
default styles are nested in merged
dictionaries three levels deep (or
deeper) the top dictionary does not
get flagged so the search skips it.
The work around is to put a default
Style to something, anything, in the
root Dictionary.
So adding a dummy style to the root dictionary fixes this. Example
<Application x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Dummy Style, anything you won't use goes -->
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</Application.Resources>
</Application>
Check your constructor in App.xaml.cs calls InitializeComponent() - this is what merges the resource dictionaries...
You should not have to reference generic.xaml at all, it has built-in support. This however means that it provides default styling, which you do not set explicitly. Explicitly set styles/templates need to be attainable from explicitly referenced res dictionaries.
(EDIT for clarity)
One exception to this is the App.xaml, where defined resources become accessible by the whole app, without requiring to reference any specific resource dictionary. The resource itself, would have to be accessible by name.
The reason why this fails
<Application.Resources>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</Application.Resources>
is, I think, because you didn't wrap it in a MergedDictionary wrapper, adding it to merged dictionaries. Adding directly to resources works only for resources you declare locally, e.g. the styles, etc. themselves.
However, as I said before, you shouldn't have to merge generic.xaml anywhere, maybe you should just refactor brushes and other resources used outside styles, and merge only those resources in app.xaml.
Also note that styles do not have to be in generic.xaml to have "default style" behaviour - if a style with key equal to the type of the element is accessible to it (globally, or in local resources), then it will use the style as a default style. The generic.xaml is just a convenience.
Check this answer.
For other custom brushes, etc, you need to reference those resources explicitly.
You should also check the contents of the WindowDictionary.xaml, this error has a certain smell about it.
I was getting this error in my unit tests and Chris' answer from above gave me the clue I needed. Basically on my first tested method, I put:
MyApplication.App app = new MyApplication.App();
app.InitializeComponent();
And suddenly it could find my template for my pages. Note: this does mean that you have to check to see if an instance of your App already exists if you are unit testing your App.cs as well.
My solution is here, click Workarounds.

Resources