WPF中如何识别点击的XAML资源内GeometryDrawing图形?
解决WPF中识别DrawingGroup内命中图形的问题
因为GeometryDrawing和DrawingGroup本身不属于FrameworkElement/FrameworkContentElement范畴,没有x:Name属性支持,没法直接通过Name区分图形,这里给你几个实用的解决思路:
方案1:利用Tag属性标记图形
在XAML里给每个需要区分的GeometryDrawing添加Tag属性,存入自定义标识:
<DrawingGroup x:Key="SvgDrawing"> <GeometryDrawing Tag="UserIcon" Brush="#FF2C5C97" Geometry="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/> <GeometryDrawing Tag="SettingsIcon" Brush="#FF888888" Geometry="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.39-1.08-.7-1.66-.94l-.38-2.65c-.03-.24-.24-.42-.48-.42h-4c-.24 0-.45.18-.48.42l-.38 2.65c-.58.24-1.14.55-1.66.94l-2.49-1c-.22-.08-.49 0-.61.22l-2 3.46c-.12.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.39 1.08.7 1.66.94l.38 2.65c.03.24.24.42.48.42h4c.24 0 .45-.18.48-.42l.38-2.65c.58-.24 1.14-.55 1.66-.94l2.49 1c.22.08.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/> </DrawingGroup>
在PreviewMouseDown事件里读取Tag判断:
private void Image_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var image = sender as Image; if (image?.Source is DrawingImage drawingImage) { var hitResult = VisualTreeHelper.HitTest(image, e.GetPosition(image)); if (hitResult.VisualHit is GeometryDrawing hitDrawing) { var shapeId = hitDrawing.Tag?.ToString(); switch (shapeId) { case "UserIcon": // 处理用户图标点击逻辑 break; case "SettingsIcon": // 处理设置图标点击逻辑 break; } } } }
方案2:自定义带标识的Drawing类
如果需要更严谨的类型约束,可以继承GeometryDrawing添加自定义标识属性:
public class IdentifiedGeometryDrawing : GeometryDrawing { public string ShapeId { get; set; } }
在XAML里引用自定义类(记得添加命名空间xmlns:local="clr-namespace:你的项目命名空间"):
<DrawingGroup x:Key="SvgDrawing"> <local:IdentifiedGeometryDrawing ShapeId="UserIcon" Brush="#FF2C5C97" Geometry="..."/> <local:IdentifiedGeometryDrawing ShapeId="SettingsIcon" Brush="#FF888888" Geometry="..."/> </DrawingGroup>
事件里直接转换为自定义类型读取属性:
private void Image_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var image = sender as Image; if (image?.Source is DrawingImage drawingImage) { var hitResult = VisualTreeHelper.HitTest(image, e.GetPosition(image)); if (hitResult.VisualHit is IdentifiedGeometryDrawing hitDrawing) { switch (hitDrawing.ShapeId) { case "UserIcon": // 对应逻辑 break; // 其他图形逻辑 } } } }
方案3:通过图形特征区分(仅适用于特征明显的场景)
如果不方便修改XAML资源,可以通过图形的边界尺寸、面积等特征来识别:
private void Image_PreviewMouseDown(object sender, MouseButtonEventArgs e) { var image = sender as Image; if (image?.Source is DrawingImage drawingImage) { var hitResult = VisualTreeHelper.HitTest(image, e.GetPosition(image)); if (hitResult.VisualHit is GeometryDrawing hitDrawing) { var bounds = hitDrawing.Geometry.Bounds; // 比如判断边界尺寸 if (Math.Abs(bounds.Width - 24) < 0.1 && Math.Abs(bounds.Height - 24) < 0.1) { // 识别为某个24x24的图形 } } } }
推荐优先用方案1或2,这两种方式稳定且易维护,方案3仅作为临时替代方案。
内容的提问来源于stack exchange,提问作者Dawnkeeper
相关产品推荐
相关产品推荐

