Привязка к преобразованиям в шаблоне ControlTemplate
-
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>
Другие советы
Предполагая, что вы всегда используете простые элементы, такие как прямоугольник, вы можете привязать высоту и ширину прямоугольника к прогрессу, а затем использовать конвертер привязки для соответствующей корректировки значения