Изменение свойств пути с помощью привязки к шаблону

#wpf #templates #data-binding #controltemplate #templatebinding

#wpf #шаблоны #привязка к данным #controltemplate #templatebinding

Вопрос:

У меня есть шаблон элемента управления, который содержит путь (помимо других элементов управления). Размер пути должен быть изменен при изменении размера элемента управления. Точки и размер, которые описывают путь, могут быть выражены в относительных долях от размера элемента управления.

Вот выдержка из шаблона:

 <Path Stroke="Gray" StrokeThickness="5">
    <Path.Data>
        <PathGeometry>
            <PathFigure StartPoint="{TemplateBinding Start}" >
                <ArcSegment Point="{TemplateBinding End}" Size="{TemplateBinding Size}" RotationAngle="0" IsLargeArc="True" />
            </PathFigure>
        </PathGeometry>
    </Path.Data>
</Path>
  

Начало и конец — это свойства зависимости от типа Point, Size — свойство зависимости от размера типа.

Что я сейчас делаю, так это прослушивание события FrameworkElement.SizeChanged:

 void OperationModeIndicator_SizeChanged( object sender, SizeChangedEventArgs e )
{
    this.Size = new Size( e.NewSize.Width * 0.45f, e.NewSize.Height * 0.45f );
    this.Start = new Point( e.NewSize.Width * 0.35f, e.NewSize.Height * 0.1f );
    this.End = new Point( e.NewSize.Width * 0.65f, e.NewSize.Height * 0.1f );
}
  

Вопрос теперь:
Есть ли другой (более элегантный) способ привязать свойства пути к размеру родительского элемента управления?

Ответ №1:

То, что у вас есть, вероятно, лучший способ добиться этого.

Другим способом было бы создать пользовательский IMultiValueConverter, который предоставляет два общедоступных свойства: WidthPercentage и HeightPercentage. Затем вы могли бы выполнить привязку к фактической ширине / фактической высоте родительского элемента шаблона.

 public class MyConverter : IMultiValueConverter {

    public double HeightPercentage { get; set; }
    public double WidthPercentage { get; set; }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
        // TODO: Validate values size and types

        return new Point(((double)values[0]) * this.WidthPercentage, ((double)values[1]) * this.HeightPercentage);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
        // No-op or throw
    }

}
  

Который вы бы использовали как:

 <local:MyConverter x:Key="StartPointConverter"
    WidthPercentage="0.35" HeightPercentage="0.1" />

<!-- ... -->

<PathFigure>
    <PathFigure.StartPoint>
        <MultiBinding Converter="{StaticResource StartPointConverter}">
            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualWidth" />
            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualHeight" />
        </MultiBinding>
    </PathFigure.StartPoint>
    <!-- ... -->
</PathFigure>