gpt4 book ai didi

c# - 将类处理程序限制为内容

转载 作者:太空宇宙 更新时间:2023-11-03 12:16:20 25 4
gpt4 key购买 nike

我有一个用户控件,里面只有一个 Canvas 。 Canvas 内部会有很多形状以及其他嵌套 Canvas 。我希望所有形状都对鼠标按下事件使用react,这样我就可以识别事件的发送者并避免显式的低级 HitTest 。但我不想为每个形状添加单独的事件订阅。

我尝试使用 EventManager.RegisterClassHandler,但随后我从我的应用程序中的所有元素获取事件,甚至是那些未包含在用户控件中的元素。

是否可以将类处理程序限制为我的用户控件的内容?是否有不同的方式来实现我想要的,即更“成熟”?

public class GraphView: UserControl
{
UIElement currentElement;

public GraphView()
{
Content = new Canvas();
HorizontalAlignment = HorizontalAlignment.Stretch;
VerticalAlignment = VerticalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Top;
HorizontalContentAlignment = HorizontalAlignment.Left;
Background = Brushes.White;
ClipToBounds = true;

EventManager.RegisterClassHandler(typeof(UIElement),
UIElement.MouseDownEvent, new RoutedEventHandler(contentMouseDown));
}

void contentMouseDown(object sender, RoutedEventArgs er)
{
MouseButtonEventArgs e = er as MouseButtonEventArgs;
if (e.LeftButton == MouseButtonState.Pressed)
{
currentElement = sender as UIElement;
}
}
}

编辑(跟进):事实证明,我实际上误解了事件在 WPF 中的工作方式,这导致我尝试使用 RegisterClassHandler。在Andy的回答让我明白了鼠标下的对象可以简单的通过RoutedEventArgs.OriginalSource获取之后,我就把事件订阅换成了标准机制

MouseLeftButtonDown += contentMouseLeftButtonDown;

感觉好多了,因为它是为此而设计的。唯一的困难是还有触发事件的模板化元素( Canvas 边框)。在那种情况下,我用 contentMouseLeftButtonDown 中的 Canvas 本身替换当前元素:

void contentMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
currentElement = e.OriginalSource as FrameworkElement;

// if there is no parent, it's a templated element
// (Border), so substitute it by the canvas itself
if (currentElement == null || currentElement.Parent == null)
currentElement = (FrameworkElement)Content;
}

最佳答案

好吧,这个解决方案是针对那些特别想使用代码来做这个并且不想了解样式、模板和命令的人。这不完全是你所得到的,因为我想证明它不会触发用户控件之外的任何东西,我也不想尝试猜测到底是什么意图。考虑到所有这些,对于经验丰富的 wpf 开发人员来说,这不太可能是解决问题的理想方式。

我的主窗口有一个带有椭圆的 Canvas 和一个用户控件。用户控件中将有另一个形状。

<Grid>
<Canvas>
<Ellipse Width="20"
Height="20"
Canvas.Left="50"
Canvas.Top="50"
Fill="Red"
/>
<Grid Height="100"
Width="100"
Canvas.Left="200">

<local:UserControl1/>
</Grid>
</Canvas>
</Grid>

我的用户控件开始时没有任何内容,代码是:

public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
Canvas canvas = new Canvas();
Rectangle rect = new Rectangle { Width = 20, Height = 20, Fill = Brushes.Blue };
Canvas.SetLeft(rect, 50);
Canvas.SetTop(rect, 50);
canvas.Children.Add(rect );
this.Content = canvas;
canvas.AddHandler(FrameworkElement.MouseLeftButtonDownEvent, new RoutedEventHandler(Canvas_MouseDown));
}
private void Canvas_MouseDown(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked me");
}
}

如果你想引用点击的特定形状,那么它作为原始源在 routedeventargs 中传递:

    private void Canvas_MouseDown(object sender, RoutedEventArgs e)
{
Shape shape = e.OriginalSource as Shape;
// Do something with the shape
}

这是使用现有事件。您的代码似乎正在尝试注册自定义路由事件。您只需按下鼠标就不需要它。

请注意,RoutedEventargs 不如您从点击事件中获得的事件参数丰富。但是形状不会有点击事件。

当我旋转它并单击椭圆时,没有任何反应。单击矩形,我得到一个消息框。这演示了为用户控件的 Canvas 的子级触发的事件。只有。

您可能会发现 Canvas 上位置设置的奇怪方式很有趣。 Canvas 具有 left 和 top 的附加属性,用于定位具有这些设置的任何子项。它们只对 Canvas 有意义,您可以将它们设置在几乎任何类型的 ui 上,无论它是否在 Canvas 中。 https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/attached-properties-overview

关于c# - 将类处理程序限制为内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49586275/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com