Я пытаюсь создать собственный элемент управления (производный от 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 ) );
}
}