添付プロパティと添付ビヘイビア
添付プロパティについて調べてみた。
参考にしたサイトはこれ。
YKSoftware - for WPF Developers
非常に分かりやすかった。
ほぼそのままお借りしてコーディングしてみます。
まずは添付プロパティのクラス。
using System; using System.Windows; using System.Windows.Controls; namespace AttachedPropertySample.AttachedProperty { public class ButtonAtt { public static bool GetIsFileRefButton(DependencyObject obj) { return (bool)obj.GetValue(IsFileRefButtonProperty); } public static void SetIsFileRefButton(DependencyObject obj, bool value) { obj.SetValue(IsFileRefButtonProperty, value); } // Using a DependencyProperty as the backing store for IsFileRefButton. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsFileRefButtonProperty = DependencyProperty.RegisterAttached("IsFileRefButton", typeof(bool), typeof(ButtonAtt), new PropertyMetadata(false, OnIsFileRefChanged)); private static void OnIsFileRefChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var b = d as Button; if(b != null) { if(GetIsFileRefButton(b)) { b.Click += OnClick; } else { b.Click -= OnClick; } } } private static void OnClick(object sender, RoutedEventArgs e) { var b = sender as Button; if (b != null) { var dlg = new Microsoft.Win32.OpenFileDialog(); var result = dlg.ShowDialog(); if (result != null && result == true) { var filename = dlg.FileName; GetCallback(b)?.Invoke(filename); } } } //callback添付プロパティ public static Action<string> GetCallback(DependencyObject obj) { return (Action<string>)obj.GetValue(CallbackProperty); } public static void SetCallback(DependencyObject obj, Action<string> value) { obj.SetValue(CallbackProperty, value); } // Using a DependencyProperty as the backing store for Callback. This enables animation, styling, binding, etc... public static readonly DependencyProperty CallbackProperty = DependencyProperty.RegisterAttached("Callback", typeof(Action<string>), typeof(ButtonAtt), new PropertyMetadata(null)); #endregion } }
次に、View。
<Window x:Class="AttachedPropertySample.View.SubView" 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:ignore="http://www.galasoft.ch/ignore" mc:Ignorable="d ignore" xmlns:att="clr-namespace:AttachedPropertySample.AttachedProperty" DataContext="{Binding Sub, Source={StaticResource Locator}}"> <Grid> <StackPanel Orientation="Vertical"> <Button x:Name="button1" Content="Button 1"/> <Button Content="Button 2" /> <Button Content="Button 3" att:ButtonAtt.IsFileRefButton="True" att:ButtonAtt.Callback="{Binding ReadFileCallback}"/> <TextBox Text="{Binding SubText}" /> </StackPanel> </Grid> </Window>
最後にViewModel。
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using AttachedPropertySample.View; using System; using System.Windows.Controls; namespace AttachedPropertySample.ViewModel { /// <summary> /// This class contains properties that a View can data bind to. /// <para> /// See http://www.galasoft.ch/mvvm /// </para> /// </summary> public class SubViewModel : ViewModelBase { private string _subText; public string SubText { get { return _subText; } set { _subText = value; RaisePropertyChanged("SubText"); } } /// <summary> /// Initializes a new instance of the SubWindowViewModel class. /// </summary> public SubViewModel() { } public Action<string> ReadFileCallback { get { return OnReadFile; } } private void OnReadFile(string obj) { SubText = obj; } } }