カスタム添付プロパティ/イベントについて質問があります。私のシナリオでは、プロパティ/イベントを任意のコントロールにアタッチしたいと考えています。このプロパティ/イベントの値は、イベント ハンドラーである必要があります。つまり、次のようになります。
<TextBox local:Dragging.OnDrag="OnDrag" />
まず、添付プロパティとして OnDrag を実装しようとしました。これは上記のケースでは機能しますが、次のケースでは失敗します。
<Style TargetType="TextBox">
<Setter Property="local:Dragging.OnDrag" Value="OnDrag" />
</Style>
"OnDrag" 文字列は、XAML システムによって RoutedEventHandler (添付プロパティの型) にできないようです。
次に試したのは、たとえば組み込みの Mouse.MouseEnter と非常によく似た、添付イベントを試して使用することでした。
この完全なコードは、下部に示されています。このバージョンでは、奇妙なことが起こっています。
示されているように (RegisterRoutedEvent 行をコメント化して) コードを実行すると、「ハンドラーの追加」関数が呼び出されたことが示されます。次に、スタイルを適用するときにxamlシステムに内部例外があります(登録されたイベントがないためだと思います)。
RegisterRoutedEvent 行を有効にしてコードを実行すると、すべてが実行されますが、「ハンドラーの追加」関数は呼び出されません。ドラッグアンドドロップマネージャーに登録できるように、それを呼び出したいのですが。
不思議なことに、EventSetter のイベントを独自のものから Mouse.MouseEnter に変更すると、xaml デザイナー (MainWindow.g[.i].cs 内) によって自動的に生成されるコードが異なります。
2) が AddXYZHandler を呼び出さない理由がわかりません。MSDNは、これが機能するはずであることを示しているようです。
最後に私の質問:
どうすればこれを機能させることができますか?それはまったく可能ですか?
シナリオに添付イベントと添付プロパティのどちらを使用するのがよいでしょうか?
プロパティの場合: OnDrag 文字列を適切な RoutedEventHandler に変換するように Style Setter を修正するにはどうすればよいですか?
イベントの場合: ここで何が問題になっていますか? これを修正する方法はありますか?AddXYZHandler を呼び出したいのですが、どうやらそれはスタイルでは機能しません。
MainWindow.xaml:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GridTest.MainWindow"
xmlns:local="clr-namespace:GridTest"
Title="MainWindow" Height="350" Width="525"
local:XYZTest.XYZ="OnXYZAttached">
<Window.Style>
<Style TargetType="Window">
<EventSetter Event="local:XYZTest.XYZ" Handler="OnXYZStyle" />
</Style>
</Window.Style>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace GridTest
{
public class XYZTest
{
//public static readonly RoutedEvent XYZEvent = EventManager.RegisterRoutedEvent("XYZ", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(XYZTest));
public static void AddXYZHandler(DependencyObject element, RoutedEventHandler handler)
{
MessageBox.Show("add handler");
}
public static void RemoveXYZHandler(DependencyObject element, RoutedEventHandler handler)
{
MessageBox.Show("remove handler");
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void OnXYZAttached(object sender, RoutedEventArgs e)
{
MessageBox.Show("attached");
}
public void OnXYZStyle(object sender, RoutedEventArgs e)
{
MessageBox.Show("style");
}
}
}
}
新しいコード:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GridTest.MainWindow"
x:Name="root"
xmlns:local="clr-namespace:GridTest"
local:XYZTest.ABC="OnXYZTopLevel"
Title="MainWindow" Height="350" Width="525">
<ListBox ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="Red" />
<Setter Property="local:XYZTest.ABC" Value="OnXYZStyle" />
<!-- <Setter Property="local:XYZTest.ABC" Value="{Binding OnXYZStyleProperty, ElementName=root}" /> -->
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Window>
using System.Windows;
namespace GridTest
{
public class XYZTest
{
public static readonly DependencyProperty ABCProperty = DependencyProperty.RegisterAttached("ABC", typeof(RoutedEventHandler), typeof(XYZTest), new UIPropertyMetadata(null, OnABCChanged));
public static void SetABC(UIElement element, RoutedEventHandler value)
{
System.Diagnostics.Debug.WriteLine("ABC set to " + value.Method.Name);
}
static void OnABCChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("ABC changed to " + ((RoutedEventHandler)e.NewValue).Method.Name);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new[] { "A", "B", "C" };
}
public void OnXYZTopLevel(object sender, RoutedEventArgs e)
{
MessageBox.Show("handler top level");
}
public void OnXYZStyle(object sender, RoutedEventArgs e)
{
MessageBox.Show("handler style");
}
public RoutedEventHandler OnXYZStyleProperty
{
get { return OnXYZStyle; }
}
}
}