I decided to go for a simpler solution and create a converter which would convert a string, being the resource key, to the icon's geometry. The converter has to make some assumptions to the location of the Icons.xaml file and the structure of its contents. The converter caches the icons geometry once accessed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Data; | |
using System.Windows.Media; | |
using System.Windows.Shapes; | |
namespace MyApp.Wpf | |
{ | |
public class StringToIconConverter : IValueConverter | |
{ | |
private static readonly ResourceDictionary _iconResource; | |
private static readonly Dictionary<string, Geometry> _pathData; | |
static StringToIconConverter() | |
{ | |
if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) | |
{ | |
_iconResource = new ResourceDictionary | |
{ | |
Source = new Uri("pack://application:,,,/Resources/Icons.xaml") | |
}; | |
_pathData = new Dictionary<string, Geometry>(); | |
} | |
} | |
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
var resourceKey = value as string; | |
return string.IsNullOrWhiteSpace(resourceKey) ? null : GetIconPathData(resourceKey); | |
} | |
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) | |
{ | |
throw new NotImplementedException(); | |
} | |
/// <summary> | |
/// Try and get the icon path data for the given resource key. | |
/// </summary> | |
/// <remarks> | |
/// This method assumes Icons.xaml from MahApps.Metro is used, and that | |
/// the icon resource is a Canvas containing a Path. | |
/// </remarks> | |
/// <param name="resourceKey">The resource key for the icon.</param> | |
/// <returns>the icon path data if found, otherwise null.</returns> | |
private static object GetIconPathData(string resourceKey) | |
{ | |
if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) | |
{ | |
Geometry iconPathData; | |
if (!_pathData.TryGetValue(resourceKey, out iconPathData)) | |
{ | |
Canvas iconCanvas = _iconResource[resourceKey] as Canvas; | |
if (iconCanvas != null) | |
{ | |
Path iconPath = iconCanvas.Children.Count > 0 ? iconCanvas.Children[0] as Path : null; | |
if (iconPath != null) | |
{ | |
iconPathData = iconPath.Data; | |
} | |
} | |
_pathData.Add(resourceKey, iconPathData); | |
} | |
return iconPathData; | |
} | |
return null; | |
} | |
} | |
} |
The objects being databound have a string property for the resource key of the icon to use, and this is bound to the a Path's Data property in the data template, which allows the Fill property to be changed dynamically.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<DataTemplate x:Key="MyDataTemplate"> | |
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="40"/> | |
</Grid.ColumnDefinitions> | |
<Path Data="{Binding Icon, Converter={StaticResource stringToIcon}}" Stretch="Uniform" Width="28" Height="28" | |
Fill="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}, Path=Foreground}" /> | |
</Grid> | |
</DataTemplate> |
No comments:
Post a Comment