Why the StaticResource cannot be resolved in this case? - wpf

I have got an exception "Cannot find resource named 'mrg'. Resource names are case sensitive." when I try to do the following:
MainWindow.xaml:
<Window.Resources>
<Thickness Left="0"
Right="1"
Bottom="2"
Top="3"
x:Key="mrg" />
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:UserControl1 />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<string> source = new List<string>()
{
"item1",
"item2",
"item3",
"item4",
"item5",
};
DataContext = source;
}
}
and UserControl1.xaml:
<Grid>
<TextBlock Text="{Binding}" Margin="{StaticResource mrg}" />
</Grid>
According to the msdn article:
Static resource lookup behavior
The lookup process checks for the requested key within the resource dictionary defined by the element that sets the property.
The lookup process then traverses the logical tree upward, to the parent element and its resource dictionary. This continues until the root element is reached.
Next, application resources are checked. Application resources are those resources within the resource dictionary that is defined by the Application object for your WPF application.
So the resource had to be found because of step 2. But, as I can see in the Locals window when exception is catched, the UserControl1.Parent == null.
I'm confused in this problem. The way I can solve it is to put the resource to the Application level.
My question is: why the StaticResource connot be found ?

The DataTemplate forms a logical tree of its own, which is disconnected from the logical tree of the ItemsControl. Hence the lookup by traversing the logical tree won't find the resource.
I wasn't able to find a reference in MSDN, just this article on CodeProject, where it reads:
The elements that are part of an expanded template, hereafter referred
to as "template elements", form their own logical tree which is
disconnected from the logical tree of the object for which they were
created.
Using DynamicResource instead of StaticResource will overcome the problem. However i can't tell exactly why. Maybe an explanation can be found in the Static resource lookup behavior and Dynamic resource lookup behavior sections in Static and Dynamic Resources, but i'm not sure.

I had a similar problem after a code cleanup. Code looked and compiled fine but would produce a "StaticResource not found error" at run time.
Changing StaticResource to DynamicResource did work. But, it really came down to App.xaml and the order in which resource dictionaries were added under the <ResourceDictionary.MergedDictionaries> section.

StaticResources must be defined before referring to them.
Faced with the unknown static link to the resource, the XAML parser throws an exception.(This problem can be solved by using a dynamic resource, but it carries the additional costs)

Related

What is the format of the DataType property for a DataTemplate or HierarchicalDataTemplate in WPF?

I am trying to understand what the format is for the DataType parameter for a DataTemplate or a HierarchicalDataTemplate. There are lots of examples scattered throughout the internet that I can copy and get working, but I don't understand what my options are.
For example:
<DataTemplate DataType="{x:Type model:DepartmentSelectionViewModel}">
I would like to understand what x:Type means. And what model:DepartmentSelectionViewModel means.
Or:
<HierarchicalDataTemplate DataType="{x:Type r:NetworkViewModel}" ItemsSource="{Binding Children}">
Again, it has x:Type. But this time r:NetworkViewModel.
Other examples will have sys: or local:. What do all these settings mean? How can I discover what other settings exist? (Is settings even the right word to describe them?)
model and r refer to XAML namespace mappings.
These are ofter found in the root tag or the XAML file and define the CLR namespaces in which the types (classes) DepartmentSelectionViewModel and NetworkViewModel are defined respectively:
<Window ... xmlns:model="clr-namespace:Project1" ... />
namespace Project1
{
public class DepartmentSelectionViewModel { ... }
}
You can define as many namespace mappings as you want.
x:Type refers to a type for which the implicit DataTemplate will be applied, i.e. the DataTemplate with the DataType property set to {x:Type model:DepartmentSelectionViewModel} will be applied to all DepartmentSelectionViewModel objects in the Items collection of the TreeView when the view is rendered.

binding combobox items to dictionary of enums

still pretty new at WPF and binding especially, but I have an enum which I will be using as properties on objects elsewhere in my project, but one of the very first kickoff points of the program will be the user selecting a single item from a combobox, which I want to match to the available enum options. I originally thought to have a dictionary object with the enum option as the key, and the value as a string for use in the UI presentation, and this is what I have been working towards. I have been searching around and thought I had it, but the combobox is populating blank.
I have a couple of questions;
Firstly, since I'm still not quite sure what is what in relation to binding, is this issue related to this post Target Exception Bug which I found in a comment on another question? If so, does this mean I'm barking up the wrong tree for the time being? And is there another way for me to achieve my goal?
Secondly, if its not related, have I missed something in the below code? I currently get no error in the output window and the project compiles fine.
Here's the enum (which lives in a separate namespace that has been added to the project references);
namespace WGM_lbr
{
public class Available_Wgms
{
private static Dictionary<Wgms,string> _wgmColl;
public static Dictionary<Wgms,string> WgmsCollection
{
get
{
return _wgmColl;
}
}
static Available_Wgms()
{
_wgmColl = new Dictionary<Wgms, string>() {
{Wgms.First, "First Dictionary item"},
//other Dictionary Items go here
}
}
public enum Wgms
{
First,
//other Enum options go here
}
}
}
My Resource declaration in app.xaml
<Application x:Class="The_First.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WGM="clr-namespace:WGM_lbr;assembly=WGM_lbr"
StartupUri="MainWindow.xaml">
<Application.Resources>
<BooleanToVisibilityConverter x:Key="b2v"/>
<WGM:Available_Wgms x:Key="WgmList"/>
</Application.Resources>
And finally the combobox and binding xaml (in case its relevant, this lives in a nest of wpf controls, up to a grid which lives on page, which is being loaded to mainwindow.xaml via a frame control using the page as the source. Both the page and mainwindow have declared the WGM namespace - I cut these out as this post is already long enough);
<ComboBox Name="cmbWgmSelector" Margin="5,0" ItemsSource="{Binding Source={StaticResource WgmList}}"/>
Any help/advice that can be provided is greatly appreciated.
Update the binding as below:
<ComboBox Name="cmbWgmSelector" Margin="5,0" DisplayMemberPath="Value" ItemsSource="{Binding Path=WgmsCollection, Source={StaticResource WgmList}}"/>

WPF DataTemplate access to Resources within same ResourceDictionary

Simplified, I have a ResourceDictionary which contains a DataTemplate and a ViewModel-Class.
<ResourceDictionary>
<DataTemplate DataType="Whatever">
<ListBox ItemsSource="{Binding Source={StaticResource MyViewModel}, Path=SomeGlobalData}" />
</DataTemplate>
<MyViewModelClass x:Key="MyViewModel" />
</ResourceDictionary>
Of course the Binding won't work (it'll fire exceptions) because the DataType won't have the resource 'MyViewModel'. But in the VisualTree the "thing" that gets DataTemplated is a child of an object which has the ResourceDictionary merged to its Resources, so there might be a way to access it within runtime.
So my question is: Is there any clean way to access 'MyViewModel' within the DataTemplate?
Your problem is the order these resources are instantiated and the fact that you use StaticResource vs DynamicResource.
A StaticResource provides a value for any XAML property attribute by looking up a reference to an already defined resource. Try to find out more on the subject.
So please move your view model above the data template if you still plan on using StaticResource.

How to declare a decimal value in XAML?

I'm able to declare an integer or double value in xaml. However, I can't add a decimal value. It builds ok, but then I get:
System.Windows.Markup.XamlParseException: The type 'Decimal' was not
found.
Here's the xaml code:
<UserControl.Resources>
<system:Int32 x:Key="AnIntValue">1000</system:Int32><!--Works!-->
<system:Double x:Key="ADoubleValue">1000.0</system:Double><!--Works!-->
<system:Decimal x:Key="ADecimalValue">1000.0</system:Decimal><!--Fails at runtime-->
</UserControl.Resources>
Here's how I'm declaring the system namespace:
xmlns:system="clr-namespace:System;assembly=mscorlib"
Edit: Workaround:
As Steven mentioned, adding the resource through code-behind seems to work fine:
Resources.Add("ADecimalValue", new Decimal(1000.0));
Edit: Answer:
Doing exactly the same thing in WPF seems to work fine. So I guess this is a hidden silverlight restriction. Thanks to Steven for this finding.
I have confirmed your finding that the Decimal type does not appear to work as a static resource in a UserControl's resources section. I do however see a couple workarounds that have been discussed here on StackOverflow, and that i have just personally verified to work with the Decimal type in Silverlight: Access codebehind variable in XAML
The workarounds include:
adding the resource from the code-behind (see the link above)
Referencing a property in the code behind using an "elementname" type binding
Accessing a public Decimal property on the user controls data context property.
The second workaround can be done like this:
<sdk:Label Name="label1" Content="{Binding ElementName=root, Path=DecimalProperty}" />
...where the root usercontrol tag is defined like this (this idea is from the link above also):
<UserControl x:Class="SilverlightDecimal.MainPage" x:Name="root" .... >
and this is in your user control's code-behind:
public decimal DecimalProperty
{
get
{
...
}
set
{
...
}
}

Programmatically Accessing a Silverlight Static Resource

I'd like to programmatically access static resources much as I would in XAML:
<TextBlock Text="{Binding Source={StaticResource My.Text.Key}}" />
This works whether my static resource is defined on the TextBlock, some parent element (e.g. UserControl) or even the application. It seems that either the StaticResource binding expression knows how to walk up the element tree, or the element itself does. I'd like to do the same thing programmatically:
<UserControl x:Class="MyCustomControl" ...>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources.xaml"/> <!-- Sets 'My.Text.Key' to System.String 'Hello, World!' -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
</UserControl>
public partial class MyCustomControl
{
public MyCustomControl()
{
InitializeComponent();
string myCustomValue = this.Resources[MyCustomValue] as string; // myCustomValue becomes null!
}
}
Even in this simple test, my resource can't seem to be accessed programmatically. And this is the simplified version of what I was trying to really do: find a static resource via an element that I have a custom dynamic property attached to (e.g. uiElement.Resources[key]).
Despite your comment to the contrary I doubt the use of "." in your resource key is really the source of your problem. In this situation the "." has no special meaning and would not impact how the resource is accessed. (I've tried and failed to reproduce any problem with it).
There is though a very big difference between using the {StaticResource MyName} mark up extension and an attempt to find the resource programmatically.
The markup extension causes the XamlParser to look for the specified key the Resources property of the FrameworkElement to which the property being assigned belongs. If the key is not found it looks for it in the parent FrameworkElement and it keeps going until it reaches the root FrameworkElement. If it is still not found it has a look in the Application's Resources property.
On the other hand this code:-
string myCustomValue = this.Resources[MyCustomValue] as string;
sf just looking in the single Resources property for the user control. No attempt is made to hunt down the key in ancestors or in the application resources. Its a simple Dictionary lookup. This I suspect is what was really tripping you up.
Having said that I would say the using "." in a resource key may not be a good idea. The "." does have meaning in various XAML scenarios already so using it in key names as well has the potential to confuse a developer reading the code even though Silverlight is quite happy with it.

Resources