WPF:Converterを使うとき、xamlのResource内で宣言をしたくないときの書き方
DataConverterを用いたコーディングは大体こんな感じ。
using System.Windows; using System.Windows.Data; namespace WpfApplication { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class viewmodel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private int val; public int Value { get { return val; } set { val = value; PropertyChanged(this,new PropertyChangedEventArgs("Value")); } } } public class MyConverter : IValueConverter { public object Convert(object value, Type type, object parameter, CultureInfo culture) { int v = (int)value; if (v > 0) { return "0より大きい!"; } return "0以下!"; } public object ConvertBack(object value, Type type, object parameter, CultureInfo culture) { //今回はViewから値が戻ってこないコントロールにバインドする前提とします return null; } } }
<Window x:Class="WpfApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication5" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:viewmodel /> </Window.DataContext> <Window.Resources> <local:MyConverter x:Key="MyConverter" /> </Window.Resources> <Grid> <TextBlock Text="{Binding Value, Converter={StaticResource MyConverter}}" /> </Grid> </Window>
上記文中の
<Window.Resources> <local:MyConverter x:Key="MyConverter" /> </Window.Resources>
これ毎回書くのも嫌ですし、App.xamlの読み込みリソースに使うConverter全部入れるのもちょっと嫌なので、考えてみました。
Converter内に
public class MyConverter : IValueConverter { … private static MyConverter _converter; public static MyConverter Converter { get { return _converter ?? (_converter = new MyConverter()); } } }
上記のスタティックプロパティを加え、利用するコントロールで
<Window x:Class="WpfApplication5.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication5" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:viewmodel /> </Window.DataContext> <Grid> <TextBlock Text="{Binding Value, Converter={x:Static local:MyConverter.Converter}}" /> </Grid> </Window>
こうすると定義はIValueConverter継承クラス内にまとまり、xamlでは宣言不要でちょっと楽かなと思いました。
3/21 追記
id:tmori3y2さん コメントに気が付かず、承認が遅れてしまって申し訳ありません。 下記のような書き換えが出来そうですね。
public class MyConverter : MarkupExtension, IValueConverter { … public override object ProvideValue(IServiceProvider serviceProvider) { return _converter ?? (_converter = new MyConverter()); } }
これですと仰る通り、
<TextBlock Text="{Binding Value, Converter={local:MyConverter}}" />
で参照可能ですね。 情報提供をありがとうございます!