1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ViewModelの文字列キーからリソースを取得するコンバーター

Posted at

はじめに

ViewModelにリソースを持つのはよくないよねー
ってことでViewModelにはキーだけで、そこからリソース本体を持ってくるコンバーターを作りました。

コンバーター本体

class StaticResourceConverter : MarkupExtension, IValueConverter
{
    private FrameworkElement _target = null;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var resourceKey = (string)value;

        return _target?.TryFindResource(resourceKey) ?? Application.Current.TryFindResource(resourceKey);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var rootObjectProvider = serviceProvider.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
        if (rootObjectProvider == null)
            return this;

        _target = rootObjectProvider.RootObject as FrameworkElement;
        return this;
    }
}

ProvideValueのおかげで、コンバーターが置いてあるXAMLのFrameworkElementが取れます。
あとはそこからTryFindResourceでリソースが持ってこれます。

使用例

わかりやすくするために、不要であろう部分を削除しています。

sample.xaml
<UserControl x:Class="FreeCellPlug.Views.Card"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:vm="clr-namespace:FreeCellPlug.ViewModels"
             xmlns:conv="clr-namespace:FreeCellPlug.Views.Converter"
             xmlns:local="clr-namespace:FreeCellPlug.Views"
             mc:Ignorable="d"              
             d:DesignHeight="350" d:DesignWidth="250" 
             d:DataContext="{d:DesignInstance {x:Type vm:CardViewModel}}">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Views/Cards/Trump.xaml"/> <!-- ここにリソースディクショナリがある -->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <ContentControl>
        <Viewbox>
            <Rectangle Fill="{Binding ResourceKey, Converter={conv:StaticResourceConverter}}" />
        </Viewbox>
    </ContentControl>
</UserControl>

MarkupExtensionを継承しているおかげで、Converter={conv:StaticResourceConverter} を追加するだけで使用できます。
TryFindResourceは、コンバーターを置いたのがRectangleでも、リソースがあるUserControlまでさかのぼってくれます。

参考:
https://stackoverflow.com/questions/695624/binding-a-datacontext-string-property-to-a-staticresource-key/695657#695657

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?