Привязки шаблонов в пользовательских элементах управления

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

  •  09-09-2019
  •  | 
  •  

Вопрос

Я просто возился с пользовательскими элементами управления в Silverlight, и хоть убей, я не могу заставить TemplateBindings работать.Может ли кто-нибудь еще раз просмотреть эту сокращенную версию и посмотреть, не упускаю ли я чего-то.

Итак, мой ControlTemplate в generic.xaml выглядит так:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:NumericStepperControl;assembly=NumericStepperControl">
    <Style TargetType="local:NumericStepper">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:NumericStepper">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>

                        <Border Grid.Column="0" BorderBrush="Black" BorderThickness="2"  Width="50" Height="30">
                            <TextBlock Width="50" Height="30" Text="{TemplateBinding Value}" />
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>        
        </Setter>
    </Style>
</ResourceDictionary>

и мой класс управления выглядит так:

namespace NumericStepperControl
{
    public class NumericStepper : Control
    {
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(NumericStepper), new PropertyMetadata(20));

        public NumericStepper()
            : base()
        {
            DefaultStyleKey = typeof( NumericStepper );
        }

        public int Value
        {
            get
            {
                return (int)GetValue(ValueProperty);
            }
            set
            {
                SetValue(ValueProperty, value);
            }
        }
    }
}

Я ожидаю, что когда это запустится, TextBlock отобразит число 20.Есть идеи, почему это не работает?

Кроме того, у меня есть отдельный проект, который содержит ссылку на сборку NumericStepperControl, и когда он запускается, элементы управления, похоже, строятся правильно.

Редактировать...после небольшого расследования я обнаружил, что если я изменю тип свойства Value на строку, то все будет работать нормально.Почему текстовый блок не просто вызывает toString для всего, что в него передается?Есть ли способ обойти это, поскольку я вижу, что это происходит часто?

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

Решение

После небольшого копания выясняется, что TextBlock на самом деле не вызывает ToString для любых передаваемых данных.Чтобы обойти эту проблему, вы должны использовать Converter для вызова ToString.

Но вот в чем проблема: TemplateBinding не поддерживает конвертеры.Вам необходимо добавить TemplateBinding в DataContext, а затем использовать обычную привязку в свойстве Text вместе с конвертером.

Таким образом, разметка TextBlock становится

 <TextBlock Width="50" Height="30" DataContext="{TemplateBinding Value}"  Text="{Binding Converter={StaticResource NumberTypeToStringConverter}}" />

Мой собственный конвертер:

public class NumberTypeToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                throw new NullReferenceException();
            } 

            return value.ToString(); 
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            MethodInfo methodInfo = targetType.GetMethod("Parse");

            if (methodInfo == null)
            {
                throw new MissingMethodException("The targetType to convert back to a Number must implement a Parse method");
            }

            return methodInfo.Invoke(null, new object[] { value });
        }
    }

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

Ваше здоровье

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

Существуют разные подходы к решению проблемы.Нашёл это описание у Марека Латушкевича..

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