Qwe*_*tie 43 .net wpf resize scrollviewer wpf-controls
我希望我Canvas自动调整大小到其项目的大小,以便ScrollViewer滚动条具有正确的范围.这可以在XAML中完成吗?
<ScrollViewer HorizontalScrollBarVisibility="Auto" x:Name="_scrollViewer">
<Grid x:Name ="_canvasGrid" Background="Yellow">
<Canvas x:Name="_canvas" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Green"></Canvas>
<Line IsHitTestVisible="False" .../>
</Grid>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,画布的大小始终为0,但它不会剪切其子元素.
Arc*_*rus 49
不,这是不可能的(请参阅下面的MSDN摘录).但是,如果您想要滚动条和自动调整大小,请考虑使用网格,并使用Margin属性将项目放置在此Grid上.网格将告诉ScrollViewer他想要的大小,并且您将获得scrollbars .. Canvas将始终告诉ScrollViewer他不需要任何大小.. :)
Grid让您享受这两个世界 - 只要您将所有元素放入单个单元格中,您就可以获得:任意定位和自动调整大小.一般来说,最好记住大多数面板控件(DockPanel,StackPanel等)都可以通过Grid控件实现.
来自MSDN:
Canvas是唯一没有固有布局特征的面板元素.Canvas的默认高度和宽度属性为零,除非它是自动调整其子元素大小的元素的子元素.画布的子元素永远不会调整大小,它们只是定位在指定的坐标处.这为不需要或不需要固有尺寸限制或对准的情况提供了灵活性.对于您希望自动调整大小和对齐子内容的情况,通常最好使用Grid元素.
希望这可以帮助
Mik*_*lls 39
我只是在这里复制illef的答案,但在回答PilotBob时,你只需定义一个像这样的画布对象
public class CanvasAutoSize : Canvas
{
protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
{
base.MeasureOverride(constraint);
double width = base
.InternalChildren
.OfType<UIElement>()
.Max(i => i.DesiredSize.Width + (double)i.GetValue(Canvas.LeftProperty));
double height = base
.InternalChildren
.OfType<UIElement>()
.Max(i => i.DesiredSize.Height + (double)i.GetValue(Canvas.TopProperty));
return new Size(width, height);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在XAML中使用CanvasAutoSize.
<local:CanvasAutoSize VerticalAlignment="Top" HorizontalAlignment="Left"></local:CanvasAutoSize>
Run Code Online (Sandbox Code Playgroud)
我更喜欢上面介绍的解决方案,它使用网格,因为它通过附加属性工作,只需要在元素上设置较少的属性.
小智 10
我认为你可以Canvas通过覆盖MeasureOverride或ArrangeOverride方法来调整大小.
这项工作并不困难.
你可以看到这篇文章.http://illef.tistory.com/entry/Canvas-supports-ScrollViewer
我希望这可以帮助你.
谢谢.
小智 6
我看到你有一个可行的解决方案,但我想我会分享.
<Canvas x:Name="topCanvas">
<Grid x:Name="topGrid" Width="{Binding ElementName=topCanvas, Path=ActualWidth}" Height="{Binding ElementName=topCanvas, Path=ActualHeight}">
...Content...
</Grid>
</Canvas>
Run Code Online (Sandbox Code Playgroud)
上述技术允许您在画布中嵌套网格并进行动态调整大小.进一步使用尺寸装订可以将动态材料与静态材料混合,执行分层等.有太多可能提及,有些比其他更难.例如,我使用该方法来模拟从一个网格位置移动到另一个网格位置的动画内容 - 在动画的完成事件中进行实际放置.祝好运.
基本上它需要完全重写Canvas.之前提出的覆盖MeasureOverride的解决方案失败,因为默认的Canvas.Left/.Top&c属性使Arrangment无效,但还需要使度量无效.(第一次获得正确的大小,但如果在初始布局后移动元素,则大小不会改变).
Grid解决方案或多或少是合理的,但为了获得xy位移而绑定到Margins会对其他代码造成严重破坏(MVVM中的特殊情况).我在网格视图解决方案上挣扎了一段时间,但View/ViewModel交互和滚动行为的复杂性最终促使我这样做.这很简单,也很重要,Just Works.
重新实现ArrangeOverride和MeasureOverride并不复杂.并且你必须在其他地方编写至少与处理网格/边距愚蠢相同的代码.你有.
这是一个更完整的解决方案.非零保证金行为未经测试.如果你需要除Left和Top之外的任何东西,那么这至少提供了一个起点.
警告:您必须使用AutoResizeCanvas.Left和AutoResizeCanvas.Top附加属性而不是Canvas.Left和Canvas.Top.剩余的Canvas属性尚未实现.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Mu.Controls
{
public class AutoResizeCanvas : Panel
{
public static double GetLeft(DependencyObject obj)
{
return (double)obj.GetValue(LeftProperty);
}
public static void SetLeft(DependencyObject obj, double value)
{
obj.SetValue(LeftProperty, value);
}
public static readonly DependencyProperty LeftProperty =
DependencyProperty.RegisterAttached("Left", typeof(double),
typeof(AutoResizeCanvas),
new FrameworkPropertyMetadata(0.0, OnLayoutParameterChanged));
private static void OnLayoutParameterChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// invalidate the measure of the enclosing AutoResizeCanvas.
while (d != null)
{
AutoResizeCanvas canvas = d as AutoResizeCanvas;
if (canvas != null)
{
canvas.InvalidateMeasure();
return;
}
d = VisualTreeHelper.GetParent(d);
}
}
public static double GetTop(DependencyObject obj)
{
return (double)obj.GetValue(TopProperty);
}
public static void SetTop(DependencyObject obj, double value)
{
obj.SetValue(TopProperty, value);
}
public static readonly DependencyProperty TopProperty =
DependencyProperty.RegisterAttached("Top",
typeof(double), typeof(AutoResizeCanvas),
new FrameworkPropertyMetadata(0.0, OnLayoutParameterChanged));
protected override Size MeasureOverride(Size constraint)
{
Size availableSize = new Size(double.MaxValue, double.MaxValue);
double requestedWidth = MinimumWidth;
double requestedHeight = MinimumHeight;
foreach (var child in base.InternalChildren)
{
FrameworkElement el = child as FrameworkElement;
if (el != null)
{
el.Measure(availableSize);
Rect bounds, margin;
GetRequestedBounds(el,out bounds, out margin);
requestedWidth = Math.Max(requestedWidth, margin.Right);
requestedHeight = Math.Max(requestedHeight, margin.Bottom);
}
}
return new Size(requestedWidth, requestedHeight);
}
private void GetRequestedBounds(
FrameworkElement el,
out Rect bounds, out Rect marginBounds
)
{
double left = 0, top = 0;
Thickness margin = new Thickness();
DependencyObject content = el;
if (el is ContentPresenter)
{
content = VisualTreeHelper.GetChild(el, 0);
}
if (content != null)
{
left = AutoResizeCanvas.GetLeft(content);
top = AutoResizeCanvas.GetTop(content);
if (content is FrameworkElement)
{
margin = ((FrameworkElement)content).Margin;
}
}
if (double.IsNaN(left)) left = 0;
if (double.IsNaN(top)) top = 0;
Size size = el.DesiredSize;
bounds = new Rect(left + margin.Left, top + margin.Top, size.Width, size.Height);
marginBounds = new Rect(left, top, size.Width + margin.Left + margin.Right, size.Height + margin.Top + margin.Bottom);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Size availableSize = new Size(double.MaxValue, double.MaxValue);
double requestedWidth = MinimumWidth;
double requestedHeight = MinimumHeight;
foreach (var child in base.InternalChildren)
{
FrameworkElement el = child as FrameworkElement;
if (el != null)
{
Rect bounds, marginBounds;
GetRequestedBounds(el, out bounds, out marginBounds);
requestedWidth = Math.Max(marginBounds.Right, requestedWidth);
requestedHeight = Math.Max(marginBounds.Bottom, requestedHeight);
el.Arrange(bounds);
}
}
return new Size(requestedWidth, requestedHeight);
}
public double MinimumWidth
{
get { return (double)GetValue(MinimumWidthProperty); }
set { SetValue(MinimumWidthProperty, value); }
}
public static readonly DependencyProperty MinimumWidthProperty =
DependencyProperty.Register("MinimumWidth", typeof(double), typeof(AutoResizeCanvas),
new FrameworkPropertyMetadata(300.0,FrameworkPropertyMetadataOptions.AffectsMeasure));
public double MinimumHeight
{
get { return (double)GetValue(MinimumHeightProperty); }
set { SetValue(MinimumHeightProperty, value); }
}
public static readonly DependencyProperty MinimumHeightProperty =
DependencyProperty.Register("MinimumHeight", typeof(double), typeof(AutoResizeCanvas),
new FrameworkPropertyMetadata(200.0,FrameworkPropertyMetadataOptions.AffectsMeasure));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75864 次 |
| 最近记录: |