I have a question regarding custom attached properties/events. In my scenario I want to attach a property/event to any control. The value of this property/event should be an event handler. In short, it should look like:
<TextBox local:Dragging.OnDrag="OnDrag" />
First I tried to implement OnDrag as an attached property. This works for the case above, but then the following case fails:
<Style TargetType="TextBox">
<Setter Property="local:Dragging.OnDrag" Value="OnDrag" />
</Style>
Because the "OnDrag" string can apparently not be made into a RoutedEventHandler (the attached property's type) by the XAML system.
The next thing I tried then was to try and use an attached event, very much like the builtin Mouse.MouseEnter for example.
The complete code for this is shown at the bottom. There are curious things happening with this version:
If you run the code as shown (with the RegisterRoutedEvent line commented) it will show the "Add handler" function is called. Then the xaml system has an internal exception when applying the style (due to missing registered event I guess).
If you run the code with the RegisterRoutedEvent line in effect everything runs, but the "Add handler" function is never called. I want it to be called though, so that I can register at the drag and drop manager.
Curiously, if I change the event in the EventSetter from my own to Mouse.MouseEnter the code that's automatically generated by the xaml designer (in MainWindow.g[.i].cs) is different.
I am not sure why 2) does not call the AddXYZHandler. MSDN seems to indicate this should work.
Finally my questions:
How can I make this work? Is it possible at all?
Do I better use an attached event or an attached property for my scenario?
in case of properties: How do I fix the Style Setter so it converts the OnDrag string to a proper RoutedEventHandler?
in case of events: What's going wrong here? Any way to fix this? I want AddXYZHandler to be called, but apparently that does not work with the style.
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");
}
}
}
}
New code:
<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; }
}
}
}