WPF自定义控件,具有自定义绘图和ActualWidth

时间:2012-05-24 10:05:46

标签: wpf xaml controls drawingcontext actualwidth

我正在尝试使用自己的绘图逻辑创建自定义控件(从 Control 派生)。控件只是从控件的左上角到右下角绘制一条对角线。此逻辑基于控件的 ActualWidth ActualHeight ,仅在呈现控件(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 ) );
  }
}

1 个答案:

答案 0 :(得分: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" ... />