akj*_*shi 2 .net wpf canvas custom-controls scrollviewer
我创建了一个继承自WPF的自定义画布控件Canvas.我在主窗口中使用它 -
<ScrollViewer
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<RTD:RTDesignerCanvas
Margin="5"
Background="White"
x:Name="canvas1"
Focusable="True"
AllowDrop="True">
</RTD:RTDesignerCanvas>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
一切正常,但是当我尝试像这样设置控件的位置时
Canvas.SetTop(item, 200);
滚动条不可见,控件隐藏在某处.有趣的是,如果我向其添加另一个控件滚动条是可见的,我可以向下滚动以查看上一个控件.
我试着用
base.InvalidateVisual();
base.UpdateLayout();
base.InvalidateArrange();
Run Code Online (Sandbox Code Playgroud)
更换物品后Top或Left没有任何反应; 我错过了什么或者由于某些错误而发生这种情况?
更新:
澄清,说我有有它的画布width,height100,100.现在,如果我用移动的控制(在画布上已添加),Canvas.SetLeft(myControl, 200)然后它会移动到这是默认情况下不可见,并且滚动条也被禁止的位置,所以没有办法看到那种控制.
现在,如果我向Canvas添加另一个控件,ScrollBars会正确显示,我可以通过滚动查看上一个控件.
您是否在自定义画布中覆盖了MeasureOverride?Canvas将始终报告DesiredSize(0,0),因此ScrollViewer永远不会认为它需要滚动.
请参阅此StackOverflow答案,该答案建议使用Grid而不是Canvas并使用Margin属性进行定位.Grid将根据子节点的大小和位置报告其大小,因此ScrollViewer将知道它需要滚动.
更新:
ScrollViewer会根据需要为其子项提供更大的大小,并且只有在子项大于ScrollViewer时才需要滚动.为了让它正确滚动,您需要报告一个足够大的DesiredSize,以包含所有子控件.你可以通过重写MeasureOverride来做到这一点:
protected override Size MeasureOverride(Size constraint)
{
base.MeasureOverride(constraint);
var desiredSize = new Size();
foreach (UIElement child in Children)
{
desiredSize = new Size(
Math.Max(desiredSize.Width, GetLeft(child) + child.DesiredSize.Width),
Math.Max(desiredSize.Height, GetTop(child) + child.DesiredSize.Height));
}
return desiredSize;
}
Run Code Online (Sandbox Code Playgroud)
但是,更简单的解决方案是利用Grid类已经如此测量的事实.您可以使用子元素的Margin属性来精确定位它们,而不是Canvas.Left和Canvas.Top属性.如果你现在在做
Canvas.SetLeft(item, 100);
Canvas.SetTop(item, 200);
Run Code Online (Sandbox Code Playgroud)
对于Canvas中的项目,您可以改为
item.Margin = new Thickness(100, 200, 0, 0);
Run Code Online (Sandbox Code Playgroud)
将它定位在单格网格中的相同位置.
| 归档时间: |
|
| 查看次数: |
4386 次 |
| 最近记录: |