Данные Silverlight привязывают int к неконтролируемому управлению - PullRequest
2 голосов
/ 14 апреля 2011

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

Код csharp выглядит так:

using System;
using System.Windows;
using System.Windows.Controls;

namespace ControlDemo
{
    public class TextControlLookless : Control
    {
        #region Title

        public static readonly DependencyProperty ChartTitleProperty =
            DependencyProperty.Register("ChartTitle", typeof(string), typeof(TextControlLookless),
            null);


        public String ChartTitle
        {
            get { return (string)GetValue(ChartTitleProperty); }
            set
            {
                SetValue(ChartTitleProperty, value);
            }
        }

        #endregion

        #region Value

        public static readonly DependencyProperty ChartValueProperty =
            DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
            null);


        public int ChartValue
        {
            get { return (int)GetValue(ChartValueProperty); }
            set
            {
                SetValue(ChartValueProperty, value);
            }
        }

        #endregion

        #region ctor

        public TextControlLookless()
        {
            this.DefaultStyleKey = typeof(TextControlLookless);
        }

        #endregion

    }
}

И xaml для элемента управления выглядит так:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ControlDemo">

<Style TargetType="local:TextControlLookless">
    <Setter Property="ChartTitle" Value="Set Title" />
    <Setter Property="ChartValue" Value="1" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:TextControlLookless">
                <Grid x:Name="Root">
                    <Border BorderBrush="Black" BorderThickness="2">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <TextBlock Text="{TemplateBinding ChartTitle}" />
                            <TextBlock Text="{TemplateBinding ChartValue}" Grid.Row="1" />
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Когда я помещаю это на страницу, я вижу ChartTitle (либо установить заголовок, либо любой другой, который я установил), но ChartValue никогда не появляется. Если я изменяю его тип на строку, он появляется, поэтому я должен что-то упустить.

1 Ответ

0 голосов
/ 15 апреля 2011

Проблема в том, что TemplateBinding является гораздо более примитивной операцией, чем Binding. Binding является реальным классом и включает некоторые полезные функции, включая неявное преобразование строк назад и вперед между другими типами данных.

TemplateBinding является чисто инструкцией по разметке, и принципиально в вашем случае не выполняет преобразование типов для вас. Следовательно, свойство зависимости, связанное со свойством Text для TextBlock, должно быть строкой.

У вас есть два варианта: -

Вместо этого можно использовать TemplateBinding, присвоив TextBlock имя и присвоив ему Text в измененном обратном вызове свойства ChartValue: -

    #region Value

    public static readonly DependencyProperty ChartValueProperty =
        DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
        new PropertyMetadata(0, OnChartValuePropertyChanged));

    private static void OnChartValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TextControlLookless source = d as TextControlLookless;
        source.Refresh();
    }


    public int ChartValue
    {
        get { return (int)GetValue(ChartValueProperty); }
        set
        {
            SetValue(ChartValueProperty, value);
        }
    }

    #endregion

    private TextBlock txtChartValue { get; set; }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        txtChartValue = GetTemplateChild("txtChartValue") as TextBlock;
        Refresh();
    }

    private void Refresh()
    {
        if (txtChartValue != null)
        {
            txtChartValue.Text = ChartValue.ToString();
        }
    }

где xaml выглядит так: -

    <TextBlock x:Name="txtChartValue" Grid.Row="1" />

Другой вариант заключается в создании частного свойства зависимости для значения с типом строки: -

        #region Value

        public static readonly DependencyProperty ChartValueProperty =
            DependencyProperty.Register("ChartValue", typeof(int), typeof(TextControlLookless),
            new PropertyMetadata(0, OnChartValuePropertyChanged));

        private static void OnChartValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            d.SetValue(ChartValueStrProperty, e.NewValue.ToString());
        }

        private static readonly DependencyProperty ChartValueStrProperty =
            DependencyProperty.Register("ChartValueStr", typeof(string), typeof(TextControlLookless),
            new PropertyMetadata("0"));

        public int ChartValue
        {
            get { return (int)GetValue(ChartValueProperty); }
            set
            {
                SetValue(ChartValueProperty, value);
            }
        }

        #endregion

где xaml выглядит так: -

        <TextBlock Text="{TemplateBinding ChartValueStr}" Grid.Row="1" />

Обратите внимание, что ChartValueStrProperty является частным, и я не удосужился создать стандартное свойство .NET для его покрытия. TemplateBinding на самом деле берет имя свойства, которому вы присваиваете суффиксы с помощью свойства, затем ищет статическое поле для целевого типа.

Оба подхода имеют свои сильные и слабые стороны. Первый подход - более распространенный шаблон, но он требует немного больше кода и менее гибок (элемент управления, отображающий значение, должен быть TextBlock). Вторая более гибкая и использует меньше кода, но несколько неортодоксальна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...