Silverlight数据绑定int到无法控制无法正常工作

时间:2011-04-14 17:20:06

标签: silverlight data-binding

我正在使用一个非常简单的无外观控件,我似乎无法使其中一个模板绑定起作用。在控件中我有两个依赖属性,一个是字符串工作,而一个是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 :(得分:0)

问题在于TemplateBinding是比Binding更原始的操作。 Binding是一个实际的类,包含一些有用的功能,包括在其他数据类型之间来回隐式转换字符串。

TemplateBinding纯粹是一个标记指令,在您的情况下,最重要的是不为您进行类型转换。因此,绑定到Text的{​​{1}}属性的依赖项属性必须是字符串。

您有两种选择: -

一种选择是使用TemplateBinding为TextBlock提供一个名称,并在TextBlock属性更改回调中指定其Text: -

ChartValue

xaml的样子: -

    #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();
        }
    }

另一种选择是为字符串类型的值创建私有依赖项属性: -

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

xaml的样子: -

        #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

请注意 <TextBlock Text="{TemplateBinding ChartValueStr}" Grid.Row="1" /> 是私有的,我没有打扰创建一个标准的.NET属性来覆盖它。 ChartValueStrProperty实际上使用您指定的属性名称后缀为“Property”,然后在目标类型上查找静态字段。

这两种方法都有其优点和缺点。第一种方法是更常见的模式,但需要更多的代码并且灵活性较差(显示值的控件必须是TextBlock)。第二种是更灵活,使用更少的代码,但有点不正统。