0

我正在尝试使用自己的绘图逻辑创建一个自定义控件(从Control派生)。该控件只是从控件的左上角到右下角绘制一条对角线。此逻辑基于控件的ActualWidthActualHeight,它们仅在呈现控件 (AFAIK) 时可用。

我的问题是,有效地进行自定义绘图的正确方法是什么?

这方面的文档不多,恐怕我在做一些愚蠢或不必要的事情,比如每次触发 OnPropertyChanged 时强制刷新/重绘......

这是控件的模板:

<Style TargetType="{x:Type local:MyCustomControl}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type local:MyCustomControl}">
        <Border Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}">
          <Canvas>
            <Line x:Name="PART_Diagonal"
                  Y1="{Binding Path=DiagonalTop}"
                  Y2="{Binding Path=DiagonalBottom}"
                  X1="{Binding Path=DiagonalLeft}"
                  X2="{Binding Path=DiagonalRight}"
                  Stroke="Red" />
          </Canvas>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

这是逻辑:

public class MyCustomControl : Control, INotifyPropertyChanged
{
  static MyCustomControl()
  {
    DefaultStyleKeyProperty.OverrideMetadata( typeof( MyCustomControl ), new FrameworkPropertyMetadata( typeof( MyCustomControl ) ) );
  }

  public MyCustomControl()
  {
    DataContext = this;
  }

  protected override void OnRenderSizeChanged( SizeChangedInfo sizeInfo )
  {
    base.OnRenderSizeChanged( sizeInfo );

    var margin = 25d;

// These calculations are based on the control's current size.
    DiagonalTop = margin;
    DiagonalBottom = ActualHeight - margin;
    DiagonalLeft = margin;
    DiagonalRight = ActualWidth - margin;

// Is this forcing redraws (i.e. invalidating the layout)?
    OnPropertyChanged( "DiagonalTop" );
    OnPropertyChanged( "DiagonalBottom" );
    OnPropertyChanged( "DiagonalLeft" );
    OnPropertyChanged( "DiagonalRight" );
  }

  public double DiagonalTop { get; private set; }
  public double DiagonalBottom{ get; private set; }
  public double DiagonalLeft { get; private set; }
  public double DiagonalRight { get; private set; }

  public event PropertyChangedEventHandler PropertyChanged;
  protected void OnPropertyChanged(string propertyname)
  {
    if (PropertyChanged != null)
      PropertyChanged.Invoke( this, new PropertyChangedEventArgs( propertyname ) );
  }
}
4

1 回答 1

3

你可以更容易地做到这一点,而无需任何额外的属性。只需将Padding属性用于内部间距:

<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
    <Border Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}" 
            BorderThickness="{TemplateBinding BorderThickness}"
            Padding="{TemplateBinding Padding}">
        <Canvas Name="DrawingCanvas">
            <Line X1="0" X2="{Binding ActualWidth, ElementName=DrawingCanvas}" 
                  Y1="0" Y2="{Binding ActualHeight, ElementName=DrawingCanvas}" 
                  Stroke="Red" />
        </Canvas>
    </Border>
</ControlTemplate>

使用带有填充的控件:

<local:MyCustomControl Padding="25" ... />
于 2012-05-24T12:07:55.173 回答