自定义控件中的模板绑定

发布于 2024-07-17 08:21:58 字数 2252 浏览 8 评论 0原文

我只是在 silverlight 中摆弄自定义控件,但在我的一生中,我无法让 TemplateBindings 工作。 有人可以重看一下这个简化版本,看看我是否遗漏了一些东西。

所以我的 generic.xaml 中的 ControlTemplate 看起来像这样

<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 ? 有没有办法解决这个问题,因为我看到这种情况经常发生?

I'm just mucking about with custom controls in silverlight and for the life of me i can't get the TemplateBindings to work. Can someone give this reduced version a once over to see if I'm missing something.

So my ControlTemplate in the generic.xaml looks like

<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>

and my control class looks like:

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

I'm expecting when this runs the TextBlock will display the number 20. Any ideas as to why this isn't working?

As a side not i have a separate project which contains a ref to the NumericStepperControl assembly and when it runs the controls seem to build correctly.

Edit... after a bit more investigation i have discovered that if i change the type of the Value property to a string that works fine. Why does a text block not just call a toString on whatever is passed into it? Is there a way round this as i can see it happening a lot?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扭转时空 2024-07-24 08:21:58

经过一番挖掘后发现,TextBlock 实际上不会对传入的任何内容调用 ToString。要解决此问题,您必须使用 Converter 来为您调用 ToString。

但问题是,TemplateBinding 不支持转换器。 您必须将 TemplateBinding 添加到 DataContext,然后在 Text 属性中使用普通 Binding 以及转换器。

因此,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 });
        }
    }

这似乎是一个解决办法,我很想听听它是否有任何不利影响。 另外,如果有人正在阅读本文并且我的转换器有任何问题,请告诉我。

干杯

After a bit of digging it turns out that the TextBlock actually doesn't call ToString on whatever is passed in. To work around this you must use a Converter to call a ToString for you.

Here's the rub though, TemplateBinding doesn't support Converters. You have to add the TemplateBinding to the DataContext and then use normal Binding in the Text property along with the converter.

So the TextBlock markup becomes

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

My custom converter:

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

This seems like a bit of a work around and i'd be interested to hear if it has any adverse implications. Also if anyone is reading this and there is anything wrong with my converter please let me know.

Cheers

盛装女皇 2024-07-24 08:21:58

有不同的方法可以解决这个问题。
找到这个Marek Latuskiewicz 的描述。

There are different approaches to get arround the problem.
Found this description by Marek Latuskiewicz.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文