Specifying resource keys using data binding
Hello!
I've been struggling with the proper way to setup a map system we've created in Noesis.
The basics are this: we have a bunch of different icons we want to display on the map: stores, monsters, other points of interest. This pretty much comes down to a list "icons" that have this type of data:
- what type of icon is it
- where is it (position, rotation)
We want to create vector icons for the map. So, up until now, we've split the icons into different lists based on the "type" if the icon. Then, we have a data template for each "type" of icon hat has it's own <Path> element that shows the icon.
The thing that is getting annoying is that now we have so many different lists of "types" of icons, and it seems somewhat silly as these are all 90% the same with just the <Path> data differing.
So, I started looking at an experiment of moving the "paths" into a separate name shared resource. That seemed to work ok:
and then i could refer to the path from a data template:
So that all seemed to work -- but now what I really want to do is instead of explicitly specifying "StoreIcon", I want that data to be bound dynamically. Ie, on my "Icon" data model, add a new "IconName" property which would be set to 'StoreIcon' or 'MonsterIcon'. ie something like this:
However, it doesn't seem like this works..
I ran into this blob post, which seems to be doing even more than what I need, but might solve it:
http://blog.functionalfun.net/2009/12/s ... ta_31.html
The method has to do with creating a converter that converts the string into the proper static resource.
Is that the best way to do this? Or is there another/better method?
thanks,
sam
I've been struggling with the proper way to setup a map system we've created in Noesis.
The basics are this: we have a bunch of different icons we want to display on the map: stores, monsters, other points of interest. This pretty much comes down to a list "icons" that have this type of data:
- what type of icon is it
- where is it (position, rotation)
We want to create vector icons for the map. So, up until now, we've split the icons into different lists based on the "type" if the icon. Then, we have a data template for each "type" of icon hat has it's own <Path> element that shows the icon.
The thing that is getting annoying is that now we have so many different lists of "types" of icons, and it seems somewhat silly as these are all 90% the same with just the <Path> data differing.
So, I started looking at an experiment of moving the "paths" into a separate name shared resource. That seemed to work ok:
Code: Select all
<Path x:Key="StoreIcon" Data="..." />
<Path x:Key="MonsterIcon" Data="..." />
Code: Select all
<Path Data="{Binding Source={StaticResource StoreIcon}, Path=Data}" />
Code: Select all
<Path Data="{Binding Source={StaticResource {Binding IconName}, Path=Data}" />
I ran into this blob post, which seems to be doing even more than what I need, but might solve it:
http://blog.functionalfun.net/2009/12/s ... ta_31.html
The method has to do with creating a converter that converts the string into the proper static resource.
Is that the best way to do this? Or is there another/better method?
thanks,
sam
-
sfernandez
Site Admin
- Posts: 2995
- Joined:
Re: Specifying resource keys using data binding
Hi Sam,
First of all I think you should be storing Geometries instead of Paths to define the icons:
You want to provide the resource key from the ViewModel, so you need a converter that can get the resource using the provided key:
The converter should be able to access the dictionary where those icon resources are defined. That can be done in several ways, maybe the dictionary can be accessed globally (they are part of the Application Resources), or the converter loads the dictionary.
The blog post you mentioned uses a custom MarkupExtension that internally sets in the target property a MultiBinding with a converter that receives the target element and the resource key, so it can just do a FindResource on the specified target element.
Please let me know if you find any trouble with this.
First of all I think you should be storing Geometries instead of Paths to define the icons:
Code: Select all
<Geometry x:Key="StoreIcon">M0,0L10,0....</Geometry>
Code: Select all
<Path Data="{Binding IconName, Converter={StaticResource IconResourceConverter}}"/>
The blog post you mentioned uses a custom MarkupExtension that internally sets in the target property a MultiBinding with a converter that receives the target element and the resource key, so it can just do a FindResource on the specified target element.
Please let me know if you find any trouble with this.
Re: Specifying resource keys using data binding
Thanks for the pointers! I was able to get this all working.
For future reference to anyone who runs into this thread, here's where I ended up:
I put all my "geometry" into a resource dictionary:
I then merged that into the global App resource dictionary.
Then, my converter ended up looking like this:
At one point I tried to specify the ResourceDictionary inline, but that broke the blend designer :(. The code above seemed to work well in Noesis as well as in blend designer.
I think the only question I have now, really, is if this is the best way to do this.. or would it be better to use something like styles? I don't know much about styles, but it seems like logically they should be able to solve a similar problem -- ie, I want an icon to show up in my "monster" style vs. the "store" style.. I haven't worked with styles much yet, though, so I'm not sure if it's better or not.
Any suggestions on the style front?
thanks,
sam
For future reference to anyone who runs into this thread, here's where I ended up:
I put all my "geometry" into a resource dictionary:
Code: Select all
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Geometry x:Key="StoreIcon">...</Geometry>
<Geometry x:Key="MonsterIcon">...</Geometry>
</ResourceDictionary>
Then, my converter ended up looking like this:
Code: Select all
class ResourceNameConverter : IValueConverter
{
private ResourceDictionary _resourceDictionary;
public ResourceDictionary ResourceDictionary
{
get => _resourceDictionary;
set => _resourceDictionary = value;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
#if NOESIS
if (value is string strValue && !string.IsNullOrEmpty(strValue))
{
LoadResourceDictionary();
if (_resourceDictionary != null && _resourceDictionary.Contains(strValue))
{
return _resourceDictionary[strValue];
}
}
return value;
#else
if (value is string strValue)
{
LoadResourceDictionary();
if (_resourceDictionary != null && _resourceDictionary.Contains(strValue))
{
return _resourceDictionary[strValue];
}
var resources = Application.Current.Resources;
if (resources != null && resources.Contains(strValue))
{
return resources[strValue];
}
}
return null;
#endif
}
private void LoadResourceDictionary()
{
if (_resourceDictionary != null)
{
return;
}
#if NOESIS
_resourceDictionary = Noesis.GUI.GetApplicationResources();
#endif
}
public Variant ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think the only question I have now, really, is if this is the best way to do this.. or would it be better to use something like styles? I don't know much about styles, but it seems like logically they should be able to solve a similar problem -- ie, I want an icon to show up in my "monster" style vs. the "store" style.. I haven't worked with styles much yet, though, so I'm not sure if it's better or not.
Any suggestions on the style front?
thanks,
sam
Re: Specifying resource keys using data binding
I used pretty much the identical technique to switch to named styles; it all seems to work ok (when the data binding changes, the style is re-evaluated).
It seems like style is more generic in terms of all the things I can do with it, so assuming the performance isn't terrible I"ll probably continue to stick with it.
thanks,
sam
It seems like style is more generic in terms of all the things I can do with it, so assuming the performance isn't terrible I"ll probably continue to stick with it.
thanks,
sam
-
sfernandez
Site Admin
- Posts: 2995
- Joined:
Re: Specifying resource keys using data binding
Using geometry resources is the most simple approach. Styles allow you to specify more things for a Path (like colors, stroke, size...), and there won't be any performance issues. I guess it all depends on what you need. The good thing about the converter is that it doesn't need to change, it is a generic way of applying resources of any type using bindings.
Who is online
Users browsing this forum: Ahrefs [Bot], Semrush [Bot] and 7 guests