In XAML, specify an Icon from another assembly - wpf

I'm new to WPF and XAML. I have the following solution which WORKS using codebehind. But it seems to me to be something that should be easier to specify in XAML.
I want to set the Icon to a resource in another assembly (specifically, so the "FlowDecisionIcon" in System.Activities.Presentation). The following code works, when added to the constructor in the codebehind:
InitializeComponent(); // This was already there
ResourceDictionary dict = new ResourceDictionary { Source = new Uri("pack://application:,,,/System.Activities.Presentation;V4.0.0.0;31bf3856ad364e35;component/themes/icons.xaml") };
this.Resources.MergedDictionaries.Add(dict);
Icon = this.Resources["FlowDecisionIcon"] as DrawingBrush;
I was hoping there would be a nice way for me to specify this either in the XAML as something like:
<Window xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
Icon="sap:FlowDecisionIcon"> ...
Or, just specify it in Visual Studio in the Properties panel for the Icon property. But I've been unsuccessful in figuring out the syntax to do either.

It seems that you're in a Window control.
<Window Icon="{DynamicReosurce FlowDecisionIcon}"
.....
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ReosurceDictionary Source="pack://application:,,,/System.Activities.Presentation;V4.0.0.0;31bf3856ad364e35;component/themes/icons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</Window>
But, it's advised to move the merging of the resources to the App.xaml file.

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 :-)

Use Resource Dictionary Styles in my class library project without merging dictionaries

I am creating a class library project that will contain WPF user controls. My Requirement is that all controls have the same style. My project looks like:
Things I have done in order to solve this problem:
Added all references needed by a WPF application System.Xaml, WindowsBase, etc.. so that I can have wpf controls in my class library project.
In AssemblyInfo.cs I have added:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Added ResourceDictionary1.xaml To the project adding the style.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="Brush1" Color="#FF19199E"/>
</ResourceDictionary>
Now if I want to use a style on my UserControl1.xaml I do:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid >
<Rectangle Fill="{StaticResource Brush1}" />
</Grid>
I know it works great but here is the catch. Every time I create a new userControl I will have to merge the dictionary. On a regular WPF application I could just merge the dictionary once on App.xaml and I will be able to use that dictionary on my entire application. How can I avoid having to merge the dictionary every time I create a new userControl? If I plan on addying a new resource dictionary I will have to go to all userControls and merge another dictionary. Perhaps I wrote the question title incorrectly and my question should have been how can I add a App.xaml file to a class library project
You should replace the source value ResourceDictionary1.xaml like the follow:
Source="pack://application:,,,/ControlsDLL;component/ResourceDictionary1.xaml">
or just simple as following:
<UserControl.Resources>
<ResourceDictionary Source="pack://application:,,,/ControlsDLL;component/ResourceDictionary1.xaml"></ResourceDictionary>
</UserControl.Resources>

How can data templates in generic.xaml get applied automatically (redux)?

This is a follow-up to a question posted by Thiado de Arruda. In short, he wanted to have a DataTemplate in his generic.xaml file, but the template wasn't being applied.
The answer given suggested placing the DataTemplate in the ControlTemplate.Resources for the control that hosted his custom type. This works very well, however, suppose that he needed the DataTemplate to apply in other places, not just within the host control. Would it be necessary to copy the DataTemplate to the ControlTemplates of every other host control?
Edit (restating question):
I am developing a WPF application using MVVM design principles. MainWindow.xaml contains the structure of the UI, and all of the styling is coded in Themes\generic.xaml. (The behavior is coded in a separate view model class, but that's irrelevant.) As part of the UI, I created a subclass of ListBox (MyListBoxSubClass) to display a collection of an ordinary .Net object of my own creation (MyObject). MyListBoxSubClass has a style in generic.xaml that redefines the Template property, and it gets applied as expected. I also have a DataTemplate for MyObject in generic.xaml, but this does not get applied. According to the above link, I have to place the DataTemplate in the Resources collection of the ControlTemplate for MyListBoxSubClass in order for this DataTemplate to be applied. This works wonderfully.
My question is how to get the DataTemplate to apply to MyObject everywhere in my application without having to duplicate the DataTemplate? I've tried adding a key to the DataTemplate and referencing it where I need it, but for some reason, I get a XAML parse error at runtime, and Resharper says that it can't resolve my DataTemplate key.
Add the data template in a separate resource dictionary in another XAML file.
Bring the XAML file into your generic.xaml control template resources:
<ControlTemplate ...>
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
</ControlTemplate>
Then wherever else you want to use this data template, you can bring it into merged dictionary of resources of wherever you want - user control, window, another control template, etc...
<Window x:Name="someWindow">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="wherever.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</Window>
Hope this helps.

Code-behind for DataTemplate in a ResourceDictionary

I am attempting to use code-behind to support an event handler in a DataTemplate. The below code works fine when it is the code-behind for a Window, but not for a ResourceDictionary. The code will not even compile when put in the code-behind for the ResourceDictionary.
I know that Commands is the better option here, but this is largely a test to make sure I can handle events on resources in a ResourceDictionary, if needed. My goal is to better organize my code, but this is not the straightforward "include" behavior that I thought a separate ResourceDictionary file would provide.
In MainWindow.xaml:
<Window x:Class="Wizbang.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:DevComponents.WpfEditors;assembly=DevComponents.WpfEditors"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:local ="clr-namespace:Wizbang"
xmlns:m ="clr-namespace:Wizbang.Model"
xmlns:vm="clr-namespace:Wizbang.ViewModel"
xmlns:vw="clr-namespace:Wizbang.View"
DataContext="{Binding Path=Main, Source={StaticResource Locator}}"
Title="Wizbang" Height="760" Width="1335" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Resources/MainWindowResources.xaml" />
</ResourceDictionary>
</Window.Resources>
In code-behind MainWindow.xaml.cs and MainWindowResources.xaml.cs, the same code:
private void btnSave_Click(object sender, RoutedEventArgs e)
{
//switch item template
Button btn = (Button)sender;
//command contains the list item
ContentControl itm = (ContentControl)btn.CommandParameter;
itm.SetValue(ContentTemplateProperty, this.FindResource("DetailedTemplate") as DataTemplate);
//this.UpdateLayout();
}
When I keep the ResourceDictionary inline in MainWindow.xaml, and put the code-behind in MainWindow.xaml.cs, everything works. When I attempt to use a separate file for ResourceDictionary, the code does not compile. The compiler complains about the last line:
itm.SetValue(ContentTemplateProperty, this.FindResource("DetailedTemplate") as DataTemplate);
The this.FindResource() is not a valid method, and "ContentTemplateProperty" is not found:
Error 4 The name
'ContentTemplateProperty' does not
exist in the current
context C:...\Visual Studio
2010\Projects\Wizbang\Wizbang\Resources\MainWindowResources.xaml.cs 36 26 Wizbang
Error 5 'Wizbang.Resources.MainWindowResources'
does not contain a definition for
'FindResource' and no extension method
'FindResource' accepting a first
argument of type
'Wizbang.Resources.MainWindowResources'
could be found (are you missing a
using directive or an assembly
reference?) C:...\Visual Studio
2010\Projects\Wizbang\Wizbang\Resources\MainWindowResources.xaml.cs 36 56 Wizbang
If I remove that last line, the code compiles and runs, but the button has no functionality. I think my issue is mapping that last line's references from the perspective of a ResourceDictionary, but I am not sure why it should be different.
Thanks for any thoughts.
Bill
This is because the code no longer is in the window class. You have to find it again (or whatever control you want to place the template on).
Window parentWindow = Window.GetWindow(btn);
itm.SetValue(Window.ContentTemplateProperty, parentWindow.FindResource("DetailedTemplate") as DataTemplate);
I think that using Commands would be a much cleaner approach.

Error when adding code behind for Silverlight resource dictionary: AG_E_PARSER_BAD_TYPE

It should be possible to add a code behind file for a resource dictionary in Silverlight, but I keep getting the same error, thrown from the InitializeComponent method of my App.xaml constructor: XamlParseException: AG_E_PARSER_BAD_TYPE.
The resource dictionary xaml file looks like this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Celerior.Annapurna.SL.ProvisiorResourceDictionary"
x:ClassModifier="public">
...
</ResourceDictionary>
If I remove the x:Class attribute everything works fine again (of course, I double-checked the class name and it's correct). My App.xaml file isn't really exciting and just contains a reference to the resource dictionary:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Celerior.Annapurna.SL.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ProvisiorResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
What am I doing wrong?
Kind regards,
Ronald Wildenberg
Silverlight does not support the x:ClassModifier thats only supported in WPF.
In addition x:Class isn't valid in a Resource dictionary. Certainly when trying to include the Xaml from the resource dictionary as a merged dictionary Silverlight wouldn't know what to do with the x:Class at that point.
Actually the above isn't strictly true x:Class is valid but the way you are including the dictionary in the application dictionary needs tweaking. Let me first just state that there is the assumption here that you actually need to sub-class ResourceDictionary (if not just drop the x:Class).
I'm also going to go out on a limb based on your inclusion of x:ClassModifier that you actually don't have a ProvisiorResourceDictionary.xaml.cs file in your project. Since SL always creates a public partial you need this file to contain at least:-
public partial class ProvisiorResourceDictionary
{
public ProvisiorResourceDictionary()
{
InitializeComponent();
}
}
That said if don't have something like this already then you may as well just drop x:Class altogether.
Now your app.xaml needs to look like this:-
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<common:ProvisiorResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Instead of trying to import the XAML file as resource via the Source property you now include an instance of the specialised ResourceDictionary.
Is the ProvisiorResourceDictionary class public? If not, maybe you need to specify the x:ClassModifier attribute as well.

Resources