C# 附加属性/事件
我有一个关于自定义附加属性/事件的问题。在我的场景中,我希望将属性/事件附加到任何控件。此属性/事件的值应为事件处理程序。简而言之,它应该是这样的:C# 附加属性/事件,c#,wpf,C#,Wpf,我有一个关于自定义附加属性/事件的问题。在我的场景中,我希望将属性/事件附加到任何控件。此属性/事件的值应为事件处理程序。简而言之,它应该是这样的: 首先,我尝试将OnDrag实现为一个附加属性。这适用于上述情况,但以下情况失败: 因为“OnDrag”字符串显然不能由XAML系统生成RoutedEventHandler(附加属性的类型) 接下来我尝试使用一个附加的事件,非常像内置的Mouse.MouseEnter 此操作的完整代码显示在底部。在这个版本中发生了一些奇怪的事情: 如果按所示
首先,我尝试将OnDrag实现为一个附加属性。这适用于上述情况,但以下情况失败:
因为“OnDrag”字符串显然不能由XAML系统生成RoutedEventHandler(附加属性的类型)
接下来我尝试使用一个附加的事件,非常像内置的Mouse.MouseEnter
此操作的完整代码显示在底部。在这个版本中发生了一些奇怪的事情:
MainWindow.xaml.cs:
使用System.Windows;
命名空间网格测试
{
公共类XYZTest
{
//公共静态只读RoutedEvent XYZEvent=EventManager.RegisterRoutedEvent(“XYZ”,RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(XYZTest));
公共静态void addxyzandler(DependencyObject元素,RoutedEventHandler处理程序)
{
Show(“添加处理程序”);
}
公共静态void Removexyzandler(DependencyObject元素,RoutedEventHandler处理程序)
{
Show(“删除处理程序”);
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
公共void OnXYZAttached(对象发送方,RoutedEventArgs e)
{
MessageBox.Show(“附件”);
}
public void OnXYZStyle(对象发送方,RoutedEventArgs e)
{
MessageBox.Show(“风格”);
}
}
}
}
新代码:
使用System.Windows;
命名空间网格测试
{
公共类XYZTest
{
public static readonly dependencProperty ABCProperty=dependencProperty.RegisterAttached(“ABC”,typeof(RoutedEventHandler),typeof(XYZTest),new UIPropertyMetadata(null,OnABCChanged));
公共静态void SetABC(UIElement元素,RoutedEventHandler值)
{
System.Diagnostics.Debug.WriteLine(“ABC设置为”+value.Method.Name);
}
更改后的静态无效(DependencyObject depObj、DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine(“ABC更改为”+((RoutedEventHandler)e.NewValue.Method.Name);
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
DataContext=new[]{“A”、“B”、“C”};
}
在XYZtopLevel上公共无效(对象发送方,路由目标)
{
MessageBox.Show(“处理程序顶层”);
}
public void OnXYZStyle(对象发送方,RoutedEventArgs e)
{
Show(“处理程序样式”);
}
公共路由EventHandler OnXYZStyleProperty
{
获取{return OnXYZStyle;}
}
}
}
我使用附加属性成功实现了拖放功能。如果我是你,我会避免为此使用自定义事件,因为你必须使用它们的参数。就个人而言,我选择了ICommand
,但您也可以使用delegate
s
请查看下面我在拖放基类实现中使用的属性和命令的列表:
/// <summary>
/// Gets or sets the type of the drag and drop object required by the Control that the property is set on.
/// </summary>
public Type DragDropType { get; set; }
/// <summary>
/// Gets or sets the allowable types of objects that can be used in drag and drop operations.
/// </summary>
public List<Type> DragDropTypes { get; set; }
/// <summary>
/// Gets or sets the ICommand instance that will be executed when the user attempts to drop a dragged item onto a valid drop target Control.
/// </summary>
public ICommand DropCommand { get; set; }
/// <summary>
/// Gets or sets the DragDropEffects object that specifies the type of the drag and drop operations allowable on the Control that the property is set on.
/// </summary>
public DragDropEffects DragDropEffects { get; set; }
/// <summary>
/// The Point struct that represents the position on screen that the user initiated the drag and drop procedure.
/// </summary>
protected Point DragStartPosition
{
get { return dragStartPosition; }
set { if (dragStartPosition != value) { dragStartPosition = value; } }
}
/// <summary>
/// The UIElement object that represents the UI element that has the attached Adorner control... usually the top level view.
/// </summary>
protected UIElement AdornedUIElement
{
get { return adornedUIElement; }
set { if (adornedUIElement != value) { adornedUIElement = value; } }
}
然后在扩展的ListBoxDragDropManager
类中:
protected override void OnAdornedUIElementPreviewDragOver(object sender, DragEventArgs e)
{
HitTestResult hitTestResult = VisualTreeHelper.HitTest(AdornedUIElement, e.GetPosition(AdornedUIElement));
ListBox listBoxUnderMouse = hitTestResult.VisualHit.GetParentOfType<ListBox>();
if (listBoxUnderMouse != null && listBoxUnderMouse.AllowDrop)
{
UpdateDropProperties(ListBoxProperties.GetDragDropType(listBoxUnderMouse), ListBoxProperties.GetDropCommand(listBoxUnderMouse));
}
UpdateDragDropEffects(listBoxUnderMouse, e);
e.Handled = true; // This bypasses base class behaviour
}
但是我必须诚实。。。这是一个很大的工作。不过,现在我只需设置几个属性就可以通过视觉反馈实现拖放操作,这似乎完全值得。谢谢您的回答。这与我所拥有的类似(不包括Telerik dragdropmanager)。在listbox的情况下,我会为项目使用一种样式。然后你就可以摆脱所有的hitbox测试了。这就是问题所在。我想写一些东西,比如OnXYZStyle只是一个常规的方法处理程序。但当您这样做时,XAML加载程序崩溃。所以我把Value=“{Binding OnXYZStyle,ElementName=root}”放在那里,但是当然我需要一个名为OnXYZStyle的属性,它返回一个委托。如果你使用ICommands,那么你可以通过一个属性返回委托来绕过我原来的问题。…DragDropManager
类是我自己的自定义类,而不是Telerik的。我不是
protected override void OnAdornedUIElementPreviewDragOver(object sender, DragEventArgs e)
{
HitTestResult hitTestResult = VisualTreeHelper.HitTest(AdornedUIElement, e.GetPosition(AdornedUIElement));
ListBox listBoxUnderMouse = hitTestResult.VisualHit.GetParentOfType<ListBox>();
if (listBoxUnderMouse != null && listBoxUnderMouse.AllowDrop)
{
UpdateDropProperties(ListBoxProperties.GetDragDropType(listBoxUnderMouse), ListBoxProperties.GetDropCommand(listBoxUnderMouse));
}
UpdateDragDropEffects(listBoxUnderMouse, e);
e.Handled = true; // This bypasses base class behaviour
}
<ListBox ItemsSource="{Binding Disc.Tracks, IsAsync=True}" SelectedItem="{Binding
Disc.Tracks.CurrentItem}" AllowDrop="True" Attached:ListBoxProperties.
IsDragTarget="True" Attached:ListBoxProperties.DropCommand="{Binding
DataContext.DropTracks, RelativeSource={RelativeSource AncestorType={x:Type
Views:ReleaseTracksView}}}" Attached:ListBoxProperties.DragDropTypes="{Binding
DataContext.DragDropTypes, RelativeSource={RelativeSource AncestorType={x:Type
Views:ReleaseTracksView}}}" Attached:ListBoxProperties.DragEffects="{Binding
DataContext.DragEffects, RelativeSource={RelativeSource AncestorType={x:Type
Views:ReleaseTracksView}}}">