强制更新画布的大小,而不更改WPF中的子内容

时间:2018-07-11 11:04:19

标签: wpf canvas resize scrollviewer

我实现了一个扩展Canvas的类,并使用MeasureOverride的覆盖根据其上子对象的排列来更新大小。

目标是在Canvas上放置可拖动的对象,这些对象可以拖到可见区域之外,并相应地进行ScrollViewer更新。

我的类重写OnMouseMove来将元素直接置于光标下方的其他元素的顶部-而不是设置Z索引,而是通过将元素从Children的{我已经扩展了Canvas,然后重新添加了元素。

将元素拖出可视区域时,滚动条会正确显示-我相信对象的删除和重新添加会触发大小更新,因为在这种情况下将调用MeasureOverride

我不希望OnMouseMove方法将元素移到顶部,但是我仍然希望在将元素拖出可视区域时显示滚动条。

如何在不更改Children的{​​{1}}内容的情况下重新计算画布的大小?

通过检测单击来进行拖动,将起点和对象直接存储在光标下方,如果在移动鼠标时拖动的元素不为null,则更新位置-拖动工作正常,但是我可以添加相关样本代码。

以下代码被混淆:

我的扩展Canvas-

Canvas

我的public class MyCanvas : Canvas { protected override void OnMouseMove(MouseEventArgs e) { UIElement isOver = (UIElement)Mouse.DirectlyOver; BringToTop(isOver); } private void BringToTop(UIElement element) { this.Children.Remove(element); this.Children.Add(element); } public void AddRect(int x, int y, int width, int height) { Rect r = new Rect(); r.Width = width; r.Height = height; Canvas.SetTop(r, x); Canvas.SetLeft(r, y); Children.Add(r); } protected override Size MeasureOverride(Size constraint) { if (InternalChildren.Count == 0) { return new Size(0,0); } base.MeasureOverride(constraint); double width = InternalChildren .OfType<UIElement>() .Max(i => i.DesiredSize.Width + (double)i.GetValue(LeftProperty)); double height = InternalChildren .OfType<UIElement>() .Max(i => i.DesiredSize.Height + (double)i.GetValue(TopProperty)); return new Size(width,height); } } MainWindow.xaml中创建一个ScrollViewer,如下所示-

DockPanel

我的<DockPanel LastChildFill="True" > <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Name="scrollViewer"> </ScrollViewer> </DockPanel> 添加了我的MainWindow.xaml.cs并插入了一些MyCanvas,如下所示-

Rect

1 个答案:

答案 0 :(得分:0)

万一有人遇到类似问题,解决方法是在鼠标悬停方法上调用InvalidateMeasure(),如下所示:

protected override void OnMouseMove(MouseEventArgs e) {
    //In this case, the class extends Canvas, so InvalidateMeasure can be 
    //called directly.
    InvalidateMeasure();

    //If using a named Canvas object (i.e. myCanvasObject), InvalidateMeasure
    //should be called on that object, not on the child objects
    myCanvasObject.InvalidateMeasure();
}