Привязка к преобразованиям в шаблоне ControlTemplate

StackOverflow https://stackoverflow.com/questions/1400381

  •  05-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь создать пользовательский элемент управления в Silverlight, который динамически масштабирует элемент в его ControlTemplate. Первая попытка ControlTemplate выглядит примерно так:

<ControlTemplate TargetType="controls:ProgressBar">
   <Grid>
      <Rectangle x:Name="TrackPart" Fill="{TemplateBinding Background}" HorizontalAlignment="Left" />
      <Rectangle x:Name="ProgressPart" Fill="Blue" >
      <Rectangle.RenderTransform>
         <ScaleTransform ScaleX="{TemplateBinding Progress}" />
            </Rectangle.RenderTransform>
         </Rectangle> 
   </Grid>
</ControlTemplate>

Однако это В ветке форума говорится, что TemplateBinding работает только с производными FrameworkElements. ScaleTransform не является FrameworkElement. Есть ли обходной путь для этого? Есть ли лучшие практики для такого рода ситуаций?

Это было полезно?

Решение

Вместо того чтобы связывать свойства ScaleX и ScaleY объекта RenderTransform, вы можете связать сам объект RenderTransform. Проблема в том, что источник является двойным значением, и вам нужно Transform. Таким образом, вы должны иметь возможность преобразовать двойное в ScaleTransform. Вы можете создать IValueConverter, чтобы сделать это:

public class TransformConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double)
        {
            double d = (double)value;
            return new ScaleTransform { ScaleY = d, ScaleX = d };
        }
        else
        {
            return new ScaleTransform();
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Вы не можете указать IValueConverter для использования в TemplateBinding, поэтому вы можете использовать обычную Binding с RelativeSource в качестве TemplatedParent. Вот так:

    <Rectangle x:Name="ProgressPart" Fill="Blue" 
           RenderTransform="{Binding Path=Progress, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource converter1}}" >

и вам нужно поместить IValueConverter в ресурсы корня ControlTemplate в области Binding:

<ControlTemplate TargetType="controls:ProgressBar">
    <Grid>
        <Grid.Resources>
            <local:TransformConverter x:Key="converter1" />
        </Grid.Resources>

Другие советы

Предполагая, что вы всегда используете простые элементы, такие как прямоугольник, вы можете привязать высоту и ширину прямоугольника к прогрессу, а затем использовать конвертер привязки для соответствующей корректировки значения

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top