访问自定义用户控件的ContentTemplate内的自定义属性

时间:2015-10-10 11:37:21

标签: c# wpf xaml

我有以下自定义用户控件:

namespace MyApp.Controls {

    public partial class ArticleButton: UserControl {

        public ArticleButton () {
            InitializeComponent ();
        }

        public static readonly DependencyProperty TitleProperty;

        static ArticleButton () {

            TitleProperty = DependencyProperty.RegisterAttached ("Title", 
                typeof (String), typeof (ArticleButton));
        }

        [Description ("The name of the article."), Category ("Common Properties")]
        public String Title {
            get { return "TEST"; }
        }
    }
}

以及相应的XAML

<UserControl x:Class="MyApp.Controls.ArticleButton"
             Name="UC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MyApp.Controls">
    <Button Name="button" Click="button_Click" Style="{StaticResource defaultButtonStyle}">
        <Button.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <TextBlock Text="{Binding Path=Title, ElementName=UC}" />
                </Grid>
            </DataTemplate>
        </Button.ContentTemplate>
    </Button>
</UserControl>

defaultButtonStyle中定义App.xaml的地方(不仅如此,但这应该足够了):

<Style TargetType="Button" x:Key="defaultButtonStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border Name="border"
                       BorderThickness="1"
                       Padding="4,2"
                       BorderBrush="DarkGray"
                       CornerRadius="3"
                       Background="{TemplateBinding Background}">
                    <Grid>
                        <ContentPresenter HorizontalAlignment="Center"
                                  VerticalAlignment="Center"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的问题是没有显示属性Title,我尝试了下面哪些都不起作用:

<TextBlock Text="{Binding Path=Title, ElementName=UC}" />
<TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource TemplatedParent}}" />
<TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type local:ArticleButton}}}" />

我发现了许多类似问题的帖子,但没有一个帮助...我认为问题是我尝试在内部按钮的内容模板中访问自定义用户控件的自定义属性,但是如何那样做。

1 个答案:

答案 0 :(得分:1)

总结评论您的第3个RelativeSource约束

<TextBlock Text="RelativeSource={RelativeSource AncestorType={x:Type local:ArticleButton}}"/>

应该可以正常使用Register代替RegisterAttached。至于其他绑定{Binding Path=Title, ElementName=UC}将不起作用,因为ConrtrolTemplate有自己的名称范围,而{Binding Path=Title, RelativeSource={RelativeSource TemplatedParent}}"将无效,因为您没有针对Button设置属性,而是{{ 1}}。

另一个问题是您针对CLR包装器设置了默认值,并且如此MSDN页面所述,CLR包装器被忽略,UserControl / GetValue方法直接调用{{1 }}

  

当加载二进制XAML和处理作为依赖项属性的属性时,WPF XAML处理器使用属性系统方法来获取依赖项属性。这有效地绕过了属性包装器。实现自定义依赖项属性时,必须考虑此行为,并且应避免在属性系统方法GetValue和SetValue之外的属性包装器中放置任何其他代码。

如果要指定默认值和/或属性更改回调,那么在创建SetValue时,还有TitleProperty方法的另一种变体,它也需要PropertyMetadata参数,您可以在其中设置这些值。

使用依赖项属性时需要注意的另一件事是,因为它的定义是静态的,所以{strong>默认值将在DependencyProperty 的所有实例之间共享。因此,如果您的类型是列表或其他类,并且您将其在Register中初始化为不同的值,那么null将同一个实例作为默认值共享

ArticleButton