我试图在WPF中创建一个自定义的wedge形状类,派生自抽象的Shape类,并且能够像在任何其他形状中一样在XAML中定义它。
我一直在Google上搜索有关如何执行此操作的完整教程,但我发现的只是自定义控件的内容。我想要的是创建一个楔形类,允许我指定内半径,外半径,这个楔形将成为360度中的多少部分(即,如果我想在圆周围安装这些楔子中的24个,这个wedge将是正确的大小,以及它的位置(它将占据的24个空间中的一个)。这些都是依赖属性,我已经注册了它们。
DefiningGeometry属性调用一个方法,该方法执行计算点和绘制形状的所有逻辑。
我遇到的问题是VS2010使用属性“模板”的设置器自动创建了一个样式。然后,当我编译时,它给我一个错误说:
“错误3无法在类型'WpfApplication1.Wedge'上找到样式属性'模板'。第8行位置17. C:\ Users \ rflint \ Desktop \ WpfApplication1 \ WpfApplication1 \ Themes \ Generic.xaml 8 17 WpfApplication1”
如果我对此进行评论,则所有内容都会编译,但楔形不会显示在表单上。如何实现此模板设置器属性?我需要吗?
XAML:
<my:Wedge CenterPoint="300,300" InnerRadius="100" OuterRadius="200" Sections="12" Position="0" Stroke="Transparent" Fill="#FFCC7329" />
C#:
protected override Geometry DefiningGeometry
{
get
{
using (StreamGeometryContext context = geometry.Open())
{
DrawWedgeGeometry(context);
}
return geometry;
}
}
private void DrawWedgeGeometry(StreamGeometryContext context)
{
double wedgeAngle = 360/Sections;
double angleA = (Position * wedgeAngle) + (wedgeAngle/2);
double angleB = (Position * wedgeAngle) - (wedgeAngle/2);
Point point1 = getPointOnCircle(CenterPoint, InnerRadius, angleA);
Point point2 = getPointOnCircle(CenterPoint, InnerRadius, angleB);
Point point3 = getPointOnCircle(CenterPoint, OuterRadius, angleB);
Point point4 = getPointOnCircle(CenterPoint, OuterRadius, angleA);
Size innerSize = new Size(InnerRadius, InnerRadius);
Size outerSize = new Size(OuterRadius, OuterRadius);
context.BeginFigure(point1, true, true);
context.ArcTo(point2, innerSize, 90, false, SweepDirection.Clockwise, true, true);
context.LineTo(point3, true, true);
context.ArcTo(point4, outerSize, 90, false, SweepDirection.Counterclockwise, true, true);
}
答案 0 :(得分:2)
我刚刚在VS2012上试过它并且工作正常,至少是一个简单的椭圆几何:
public sealed class Wedge : Shape
{
public Double Radius
{
get { return (Double)this.GetValue(RadiusProperty); }
set { this.SetValue(RadiusProperty, value); }
}
public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register(
"Radius", typeof(Double), typeof(Wedge), new PropertyMetadata(0.0));
protected override Geometry DefiningGeometry
{
get {return new EllipseGeometry(new Point(0, 0), this.Radius, this.Radius); }
}
}
和XAML:
<local:Wedge Radius="50" Stroke="Black" Fill="Yellow" StrokeThickness="2" Canvas.Top="100" Canvas.Left="100" />
答案 1 :(得分:0)
让我为您的问题提供一个简单的解决方案:
public class Wedge : Shape
{
public Double StartAngle
{
get { return (Double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(Double), typeof(Wedge), new PropertyMetadata(0d));
public Double EndAngle
{
get { return (Double)GetValue(EndAngleProperty); }
set { SetValue(EndAngleProperty, value); }
}
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(Double), typeof(Wedge), new PropertyMetadata(0d));
public Point Center
{
get { return (Point)GetValue(CenterProperty); }
set { SetValue(CenterProperty, value); }
}
public static readonly DependencyProperty CenterProperty =
DependencyProperty.Register("Center", typeof(Point), typeof(Wedge), new PropertyMetadata(new Point()));
public Double InnerRadius
{
get { return (Double)GetValue(InnerRadiusProperty); }
set { SetValue(InnerRadiusProperty, value); }
}
public static readonly DependencyProperty InnerRadiusProperty =
DependencyProperty.Register("InnerRadius", typeof(Double), typeof(Wedge), new PropertyMetadata(0d));
public Double OuterRadius
{
get { return (Double)GetValue(OuterRadiusProperty); }
set { SetValue(OuterRadiusProperty, value); }
}
public static readonly DependencyProperty OuterRadiusProperty =
DependencyProperty.Register("OuterRadius", typeof(Double), typeof(Wedge), new PropertyMetadata(0d));
protected override Geometry DefiningGeometry
{
get
{
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext context = geometry.Open())
{
Draw(context);
}
return geometry;
}
}
private void Draw(StreamGeometryContext context)
{
var isStroked = Stroke != null & Stroke != Brushes.Transparent & StrokeThickness > 0;
var isFilled = Fill != null & Fill != Brushes.Transparent;
context.BeginFigure(
GetPointOnCircle(Center, OuterRadius, StartAngle),
isFilled,
true);
context.ArcTo(
GetPointOnCircle(Center, OuterRadius, EndAngle),
new Size(OuterRadius, OuterRadius),
0,
EndAngle - StartAngle > 180,
SweepDirection.Clockwise,
isStroked,
true);
context.LineTo(GetPointOnCircle(Center, InnerRadius, EndAngle), isStroked, true);
context.ArcTo(
GetPointOnCircle(Center, InnerRadius, StartAngle),
new Size(InnerRadius, InnerRadius),
0,
EndAngle - StartAngle > 180,
SweepDirection.Counterclockwise,
isStroked,
true);
context.LineTo(GetPointOnCircle(Center, OuterRadius, StartAngle), isStroked, true);
}
private Point GetPointOnCircle(Point center, double radius, double angle)
{
var px = center.X + radius * Math.Cos(ToRadians(angle));
var py = center.Y + radius * Math.Sin(ToRadians(angle));
return new Point(px, py);
}
public double ToRadians(double angle)
{
return angle * Math.PI / 180;
}
}