独自の描画ロジックを使用してカスタムコントロール( 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 ) );
}
}