Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF鼠标事件路由问题 以下是我正在尝试做的:_C#_Wpf_Mouseevent - Fatal编程技术网

C# WPF鼠标事件路由问题 以下是我正在尝试做的:

C# WPF鼠标事件路由问题 以下是我正在尝试做的:,c#,wpf,mouseevent,C#,Wpf,Mouseevent,构建一个基本上是滚动树视图的自定义控件。稍后,它将不得不以某种方式监控和交互其项目。(例如,它必须找到对应于名称路径的元素)。由于所有项目都具有相同的大小,因此这也是虚拟化的主要情况;) 毫不奇怪,这些元素应该支持基本的交互,比如(视觉上)响应鼠标悬停在它们上面 下面是我如何尝试的: 实际的树类有一个Items属性(它是一个IList)和两个滚动条作为它的可视子级,并覆盖度量、排列和渲染(希望忽略几个不相关的函数): 什么不起作用: 我的主要问题是子元素似乎没有得到mousedown事件(或其他

构建一个基本上是滚动树视图的自定义控件。稍后,它将不得不以某种方式监控和交互其项目。(例如,它必须找到对应于名称路径的元素)。由于所有项目都具有相同的大小,因此这也是虚拟化的主要情况;)

毫不奇怪,这些元素应该支持基本的交互,比如(视觉上)响应鼠标悬停在它们上面

下面是我如何尝试的: 实际的树类有一个Items属性(它是一个IList)和两个滚动条作为它的可视子级,并覆盖度量、排列和渲染(希望忽略几个不相关的函数):

什么不起作用: 我的主要问题是子元素似乎没有得到mousedown事件(或其他鼠标事件)。也许我没有得到整个视觉树和路由事件的东西,但我从来没有看到控制台输出时,我点击该项目。在树上,我可以同时获得previewmousdown和MousedDown事件

此外,内部控件不会剪裁到内部显示区域(为什么要剪裁),我可以通过在排列滚动条和覆盖GetLayoutClip之前排列它们来解决这个问题。或者,我可以尝试让孩子们意识到他们的水平偏移,并简单地将他们安排在一个不合适的矩形中。但是,我确实想知道是否有更好的方法:)

确保您正在为您的每个孩子打电话。仅仅覆盖VisualChildrenCount和GetVisualChild是不够的;框架还需要了解这种关系。(也许您是在“无关函数”中这样做的。)

虚拟化确实很难实现,与其尝试从头开始构建虚拟化,不如尝试使用的功能。看起来您正在垂直堆叠元素,并在每个深度缩进子元素。您可以使用逻辑将层次结构数据展平到单个列表中,该列表存储原始节点和嵌套级别。然后可以使用VirtualzingStackPanel将该列表绑定到ItemsControl,并根据嵌套级别设置每个容器的左边距


如果您最终实现了自己的虚拟化控件,那么您可能希望直接从中继承。下面是一系列博客文章,介绍了实现虚拟化面板所需的一切:

您当前的解决方案由于没有利用TreeView、ItemsControl、Control、ScrollViewer或任何面板的任何内置功能而损失惨重。您现在基本上是在WPF中进行WinForms编程。是什么让你决定沿着这条路走,而不是从TreeView或其他ItemsControl开始并根据需要修改它?非常感谢!它确实也调用了缺少的AddVisualChild:)现在,我也明白了为什么VisualCollection构造函数需要对父级VisualChild的引用——当添加了一些东西时,它会自动调用AddVisualChild(这就是滚动条神奇工作的原因)
public sealed partial class SyncTree : Control
{
    ScrollBar verticalScrollbar = new ScrollBar();
    ScrollBar horizontalScrollbar = new ScrollBar();

    private VisualCollection visualchildren;

    protected override int VisualChildrenCount
    {
        get
        {
            return visualchildren.Count + Items.Count;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < visualchildren.Count)
            return visualchildren[index];
        else
            return Items[index - visualchildren.Count];
    }

    private Size MeasuredSize = new Size(0, 0);

    protected override Size MeasureOverride(Size availableSize)
    {
        UpdateMeasuredSize();
        return availableSize;
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        ArrangeItems(ArrangeScrollbars(arrangeBounds));
        return arrangeBounds;
    }

    private void ArrangeItems(Size arrangeBounds)
    {
        var y = Padding.Top - verticalScrollbar.Value;
        foreach (var item in Items)
        {
            item.Arrange(new Rect(Padding.Left - horizontalScrollbar.Value, y, item.Width, item.Height));

            y += item.Height;
            y += RootNodeSpacing;
        }
    }

    protected override void OnRender(DrawingContext context)
    {
        //kill the ugly background-colored patch between the scrollbars
        if (verticalScrollbar.IsVisible && horizontalScrollbar.IsVisible) context.DrawRectangle(verticalScrollbar.Background, null, new Rect(RenderSize.Width - verticalScrollbar.Width, RenderSize.Height - horizontalScrollbar.Height, verticalScrollbar.Width, horizontalScrollbar.Height));

        context.DrawRectangle(Background, null, new Rect(RenderSize));
    }
}
public class SyncTreeItem : Control
{
    protected override Size MeasureOverride(Size constraint)
    {
        var size = new Size(FormattedText.Width + FormattedText.Height + 5, FormattedText.Height);
        if (IsExpanded)
        {
            foreach (var item in Items)
            {
                item.Measure(new Size(constraint.Width - Indent, constraint.Height - size.Height));
                size.Height += item.DesiredSize.Height;
                size.Width = Math.Max(size.Width, item.DesiredSize.Width + Indent);
            }
        }
        Height = size.Height;
        Width = size.Width;
        return size;
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        if (IsExpanded)
        {
            var y = FormattedText.Height;
            foreach (var item in Items)
            {
                item.Arrange(new Rect(Indent, y, item.Width, item.Height));
                y += item.Height;
            }
            return new Size(arrangeBounds.Width, y);
        }
        else return new Size(arrangeBounds.Width, FormattedText.Height);
    }

    protected override void OnRender(DrawingContext context)
    {
        context.DrawRectangle(Brushes.Transparent, null, new Rect(new Point(0, 0), RenderSize));
        context.PushClip(new RectangleGeometry(new Rect(RenderSize)));

        var ft = FormattedText;

        context.DrawImage(Icon, new Rect(0, 0, ft.Height, ft.Height));
        context.DrawText(ft, new Point(ft.Height + 5, 0));
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        Console.WriteLine("got mousedown!");
    }
}