You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:45:59