我想要一个图像作为背景,可以均匀拉伸 . 然后我希望我的画布的大小等于均匀拉伸的图像 . (我找到的解决方法是在网格内部使用图像和画布,并将画布宽度/高度绑定到图像的实际高度/宽度) .
然后我想在画布内有绝对定位的项目 . 但这是问题 . 如果项目X是50,图像是200px宽度,那么它的确定 . 但是如果图像得到100px宽度,则项目X应该是25.我也想要一个小规模的变换 . 有没有办法通过绑定实现这一目标?我是否必须实现我的自定义面板用户控件,因为我看不到其他清洁解决方案 .
你当然可以通过绑定实现所有这一切,但我想创建一个派生面板可以更轻松,更清晰,它可以将儿童安排在相对于面板的ActualWidth和Actualheight的位置 .
派生的Panel类可以定义子位置的附加属性,类似于Canvas.Left和Canvas.Top,但小数值范围从0到1 .
它还可以将背景图像保持为依赖属性 . 您将覆盖OnRender方法以直接绘制此图像 .
小组还可以计算当前比例因子,例如,除以它的ActualWidth由图像的宽度决定 . 适当的ScaleTransform属性可以很容易地附加到每个孩子的RenderTransform .
编辑:除了面板相对于背景图像的维度的一致性之外,以下内容可能会让您了解该面板的实现方式:
public class ImagePanel : Panel { public static readonly DependencyProperty LeftProperty = DependencyProperty.RegisterAttached( "Left", typeof(double), typeof(ImagePanel), new FrameworkPropertyMetadata(PositionChanged)); public static readonly DependencyProperty TopProperty = DependencyProperty.RegisterAttached( "Top", typeof(double), typeof(ImagePanel), new FrameworkPropertyMetadata(PositionChanged)); public static readonly DependencyProperty ImageProperty = DependencyProperty.Register( "Image", typeof(ImageSource), typeof(ImagePanel), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)); private ScaleTransform scaleTransform = new ScaleTransform(); 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 double GetTop(DependencyObject obj) { return (double)obj.GetValue(TopProperty); } public static void SetTop(DependencyObject obj, double value) { obj.SetValue(TopProperty, value); } public ImageSource Image { get { return (ImageSource)GetValue(ImageProperty); } set { SetValue(ImageProperty, value); } } protected override void OnRender(DrawingContext dc) { if (Image != null) { dc.DrawImage(Image, new Rect(0d, 0d, ActualWidth, ActualHeight)); } base.OnRender(dc); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { base.OnRenderSizeChanged(sizeInfo); if (Image != null) { scaleTransform.ScaleX = sizeInfo.NewSize.Width / Image.Width; scaleTransform.ScaleY = sizeInfo.NewSize.Height / Image.Height; } } protected override Size MeasureOverride(Size availableSize) { foreach (UIElement element in InternalChildren) { element.Measure(availableSize); } return new Size(); } protected override Size ArrangeOverride(Size finalSize) { foreach (UIElement element in InternalChildren) { element.RenderTransform = scaleTransform; ArrangeElement(element, finalSize.Width, finalSize.Height); } return finalSize; } private static void PositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var element = obj as UIElement; var panel = VisualTreeHelper.GetParent(obj) as ImagePanel; if (element != null && panel != null) { ArrangeElement(element, panel.ActualWidth, panel.ActualHeight); } } private static void ArrangeElement(UIElement element, double width, double height) { var left = GetLeft(element); var top = GetLeft(element); var rect = new Rect(new Point(left * width, top * height), element.DesiredSize); element.Arrange(rect); } }
1 回答
你当然可以通过绑定实现所有这一切,但我想创建一个派生面板可以更轻松,更清晰,它可以将儿童安排在相对于面板的ActualWidth和Actualheight的位置 .
派生的Panel类可以定义子位置的附加属性,类似于Canvas.Left和Canvas.Top,但小数值范围从0到1 .
它还可以将背景图像保持为依赖属性 . 您将覆盖OnRender方法以直接绘制此图像 .
小组还可以计算当前比例因子,例如,除以它的ActualWidth由图像的宽度决定 . 适当的ScaleTransform属性可以很容易地附加到每个孩子的RenderTransform .
编辑:除了面板相对于背景图像的维度的一致性之外,以下内容可能会让您了解该面板的实现方式: