LoginSignup
10
8

More than 5 years have passed since last update.

ViewModelでStyleを指定する方法。StyleConverterでFindResource汚染を回避

Last updated at Posted at 2015-08-15

はじめに

MVVMで永遠に付いて回る悩みの一つは、Viewの持ち物であるデザインリソースをViewModelといかに切り離すかです。
例えば、カラーやブラシなどロジックとは関係ないリソースは、ViewModelでは持たずリソースのキー名だけで管理できるのが理想です。
WPFには、FindResource関数が用意されていますが、コイツは、リソース本体を読み込んで返すという基本的な関数なためViewModelに、重たいリソース情報を持つことになります。
また、Viewの参照も必要とするためMVVMとは相性の良くない機能です。

Styleを活用する

WPFには、Styleという機能が用意されています。
ご存じない方に一言で説明するならば、プロパティ値の集合がStyleです。
Xamlのタグに、Windth="100"というようにプロパティ設定を行いますが、このWindth="100"という部分だけを纏めたものがStyleです。
そのためターゲットとなるオブジェクトによって、設定できるプロパティ名は変わってきます。
ViewModelから状態によって、見た目を変化させるというプログラムの多くは、Styleを切り替える事で実現出来るはずです。

StyleConverterを制作する

疎結合を保つためViewModelには、リソースのキー名だけを持つようにします。
Xamlの受け手のStyle=""は、Styleクラスですので、そのままバインディングできません。
このように、バインディング値を変換しなければならない時には、Converterという仕組みを利用します。

StyleConverter.cs
public class StyleConverter : IMultiValueConverter 
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        FrameworkElement targetElement = values[0] as FrameworkElement;
        string styleName = values[1] as string;

        if (styleName == null)
        {
            return null;
        }
        Style newStyle = (Style)targetElement.TryFindResource(styleName);

        return newStyle;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

上記のコードが、StyleConverterの実装例です。

呼び出し例

呼び出しは、マルチバインディングを使っています。
1つ目が、リソースを格納しているオブジェクトへの参照で、2つ目が、キー名となります。
ViewModelの記述は、割愛します。

Test.xaml
<Button>
    <Button.Style>
        <MultiBinding>
            <MultiBinding.Converter>
                <converters:StyleConverter />
            </MultiBinding.Converter>
            <MultiBinding.Bindings>
                <Binding RelativeSource="{RelativeSource Self}" />
                <Binding Path="ButtonStyle" />
            </MultiBinding.Bindings>
        </MultiBinding>
     </Button.Style>
</Button>
10
8
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
10
8