2016-02-29 121 views
2

我想创建一个自定义Shape调节控制,即绘制不同的形状,如PolygonEllipseRectangle等,这取决于一些自定义属性。创建自定义形状在UWP(通用的Windows应用程序)时,Windows 10

我能够创建一个自定义模板控制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方法,以及里面插入的shapeParentContentControl

相应Shape控制但我” d喜欢实际上扩展Shape,所以我可以用相同的方式处理所有形状,framewok和custom。

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

如何创建自定义的Shape控件并定义相应的几何图形?

回答

3

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

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

设置Data导致另一个布局来看,所以设置它什么,它是在调用会导致一个例外:检测

布局循环。布局不能完成

我使用的方式是注册属性更改事件的处理程序,并更新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); 
    } 
} 
+0

这包括你的使用情况,但是当你想要与固定点和其他依赖于大小一些地方自定义的耻辱,会发生什么,这样的吗? http://stackoverflow.com/questions/43761186/how-to-create-a-speech-bubble-in-uwp矩形部分取决于大小,但尖角部分是固定的。 – SuperJMN

相关问题