gpt4 book ai didi

c# - 在 UWP(通用 Windows 应用程序)、Windows 10 中创建自定义形状控件

转载 作者:行者123 更新时间:2023-11-30 21:51:24 25 4
gpt4 key购买 nike

我想创建一个自定义的 Shape 控件,它绘制不同的形状,如 PolygonEllipseRectangle等,具体取决于一些自定义属性。

我能够像这样创建自定义模板控件 ColorShape:

<Style TargetType="local:CustomShape">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomShape">
<ContentControl x:Name="shapeParent">
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

然后,重写OnTemplateChanged方法,在shapeParentContentControlShape控件中插入对应的Shape控件/p>

但我想要的是实际扩展 Shape,这样我就可以以相同的方式处理所有形状、框架和自定义。

在 WPF 中,我们能够扩展 Shape 并覆盖属性 DefiningGeometry。在 UWP 中,不存在任何要覆盖的 DefiningGeometry 属性。

如何创建自定义 Shape 控件并定义相应的 Geometry?

最佳答案

我发现在 UWP 中创建自定义形状的唯一方法是扩展 Path类并设置其 Data属性(property)。

更新 Data 属性以说明其他依赖属性(如 Width)的变化不能在布局相关部分中完成,如 LayoutUpdated 事件或 ArrangeOverride 方法。

设置 Data 会导致另一次布局运行,因此将其设置在在此期间调用的任何内容中都会导致异常:

Layout cycle detected. Layout could not complete

我使用的方法是为属性更改事件注册处理程序并更新其中的Data

我写了一个blog post更详细地解释了它。

这是我使用的例子:

public class CandlestickShape : Path
{
public double StartValue
{
get { return Convert.ToDouble(GetValue(StartValueProperty)); }
set { SetValue(StartValueProperty, value); }
}
public static readonly DependencyProperty StartValueProperty =
DependencyProperty.Register("StartValue", typeof(double), typeof(CandlestickShape), new PropertyMetadata(0));

public double EndValue
{
get { return Convert.ToDouble(GetValue(EndValueProperty)); }
set { SetValue(EndValueProperty, value); }
}
public static readonly DependencyProperty EndValueProperty =
DependencyProperty.Register("EndValue", typeof(double), typeof(CandlestickShape), new PropertyMetadata(0));

public double MinValue
{
get { return Convert.ToDouble(GetValue(MinValueProperty)); }
set { SetValue(MinValueProperty, value); }
}
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double), typeof(CandlestickShape), new PropertyMetadata(0));

public double MaxValue
{
get { return Convert.ToDouble(GetValue(MaxValueProperty)); }
set { SetValue(MaxValueProperty, value); }
}
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double), typeof(CandlestickShape), new PropertyMetadata(0));

/// <summary>
/// Defines how many Pixel should be drawn for one Point
/// </summary>
public double PixelPerPoint
{
get { return Convert.ToDouble(GetValue(PointsPerPixelProperty)); }
set { SetValue(PointsPerPixelProperty, value); }
}
public static readonly DependencyProperty PointsPerPixelProperty =
DependencyProperty.Register("PixelPerPoint", typeof(double), typeof(CandlestickShape), new PropertyMetadata(0));

public CandlestickShape()
{
this.RegisterPropertyChangedCallback(CandlestickShape.WidthProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
this.RegisterPropertyChangedCallback(CandlestickShape.StartValueProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
this.RegisterPropertyChangedCallback(CandlestickShape.EndValueProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
this.RegisterPropertyChangedCallback(CandlestickShape.MinValueProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
this.RegisterPropertyChangedCallback(CandlestickShape.MaxValueProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
this.RegisterPropertyChangedCallback(CandlestickShape.PointsPerPixelProperty, new DependencyPropertyChangedCallback(RenderAffectingPropertyChanged));
}

private void RenderAffectingPropertyChanged(DependencyObject o, DependencyProperty e)
{
(o as CandlestickShape)?.SetRenderData();
}

private void SetRenderData()
{
var maxBorderValue = Math.Max(this.StartValue, this.EndValue);
var minBorderValue = Math.Min(this.StartValue, this.EndValue);
double topLineLength = (this.MaxValue - maxBorderValue) * this.PixelPerPoint;
double bottomLineLength = (minBorderValue - this.MinValue) * this.PixelPerPoint;
double bodyLength = (this.EndValue - this.StartValue) * this.PixelPerPoint;

var fillColor = new SolidColorBrush(Colors.Green);
if (bodyLength < 0)
fillColor = new SolidColorBrush(Colors.Red);

bodyLength = Math.Abs(bodyLength);

var bodyGeometry = new RectangleGeometry
{
Rect = new Rect(new Point(0, topLineLength), new Point(this.Width, topLineLength + bodyLength)),
};

var topLineGeometry = new LineGeometry
{
StartPoint = new Point(this.Width / 2, 0),
EndPoint = new Point(this.Width / 2, topLineLength)
};

var bottomLineGeometry = new LineGeometry
{
StartPoint = new Point(this.Width / 2, topLineLength + bodyLength),
EndPoint = new Point(this.Width / 2, topLineLength + bodyLength + bottomLineLength)
};

this.Data = new GeometryGroup
{
Children = new GeometryCollection
{
bodyGeometry,
topLineGeometry,
bottomLineGeometry
}
};
this.Fill = fillColor;
this.Stroke = new SolidColorBrush(Colors.Black);
}

protected override Size ArrangeOverride(Size finalSize)
{
double height = (MaxValue - MinValue) * PixelPerPoint;
return new Size(this.Width, height);
}

protected override Size MeasureOverride(Size availableSize)
{
double height = (MaxValue - MinValue) * PixelPerPoint;
return new Size(this.Width, height);
}
}

关于c# - 在 UWP(通用 Windows 应用程序)、Windows 10 中创建自定义形状控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35697991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com