繁体   English   中英

WPF,无法绑定属性,因为它说它不是DependencyProperty,但是我注册了它

[英]WPF, cannot bind a property because it says it's not a DependencyProperty, but I registered it

我有一个带有Template属性的UserControl ,它已设置为DependencyProperty

public partial class TemplateDetail : UserControl
{
    public static readonly DependencyProperty _templateProperty =
        DependencyProperty.Register(
            "Template",
            typeof(Template),
            typeof(TemplateDetail)
        );

    public TemplateDetail()
    {
        InitializeComponent();
        Template = new Template();
        DataContext = Template;
    }

    public Template Template
    {
        get
        {
            return (Template)GetValue(_templateProperty);
        }
        set { SetValue(_templateProperty, value); }
    }
}

我试图在XAML中为Window ,SaveTemplateDialog使用此UserControl ,并且尝试将其Template属性设置为SaveTemplateDialog类中的Template属性:

<local:TemplateDetail HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                      MinWidth="100" Template="{Binding}"
                      Width="{Binding ElementName=Scroller, Path=ViewportWidth}"/>

SaveTemplateDialogDataContext设置为其Template属性,这也是一个依赖项属性。 但是,对于上述XAML,在Visual Studio中, Template="{Binding}"用蓝色下划线标出,并指出:

不能在'TemplateDetail'类型的'Template'属性上设置'Binding'。 只能在DependencyObject的DependencyProperty上设置“绑定”。

果然,当我加载应用程序时,当我知道其中包含值时, TemplateDetail尝试显示的Template内容为空白。 如果我已经将TemplateDetail.Template注册为依赖项属性,为什么它会显示此消息?

编辑:现在我很困惑。 在我的SaveTemplateDialog窗口中,我正在执行以下操作以将模板传递给TemplateDetail UserControl

<local:TemplateDetail HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                      TemplateData="{Binding Path=NewTemplate, Mode=OneWay}"
                      Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3"/>

我知道Path=NewTemplate是获得正确的数据,因为我也有这个XAML中SaveTemplateDialog ,这说明我希望在价值MyType财产NewTemplate

<TextBlock Text="{Binding Path=NewTemplate.MyType}" />

TextBlock显示了我的期望。 但是,显然正确的数据没有到达TemplateDetail或者我在那里没有正确绑定,因为我无法获得相同的MyType属性(或其他Template属性)显示在TemplateDetail TemplateDetail

<TextBlock Text="{Binding Path=TemplateData.MyType}" Grid.Row="2" Grid.Column="2"
           HorizontalAlignment="Stretch" Width="200"/>

这是现在的TemplateDetail类:

public partial class TemplateDetail : MainWindowUserControl
{
    public static readonly DependencyProperty TemplateDataProperty =
        DependencyProperty.Register(
            "TemplateData",
            typeof(Template),
            typeof(TemplateDetail),
            new PropertyMetadata(
                new Template("Default Template", null)
            )
        );

    public TemplateDetail()
    {
        InitializeComponent();
        DataContext = this;
    }

    public Template TemplateData
    {
        get
        {
            return (Template)GetValue(TemplateDataProperty);
        }
        set { SetValue(TemplateDataProperty, value); }
    }
}

您应该将DependencyProperty的名称更改为使用类似于PropertyNameProperty的标准约定,而不是像字段一样命名。 当您在XAML中进行设置时,它将调用SetValue并期望使用字符串名称(此处为“ Template”)和“ Property”来命名属性。

更新第二个问题:

当您在TemplateDetail构造函数中设置DataContext = this时,导致Path = NewTemplate绑定的源从继承的DataContext更改为TemplateDetail控件本身。 您应该在“输出”窗口中看到一个错误,指出在TemplateDetail类型的对象上找不到NewT​​emplate属性。 我通常不重设UserControl本身的DataContext,而通常给UserControl XAML中的根布局Panel一个x:Name,并在构造函数中设置LayoutRoot.DataContext = this

确保模板不是导致XAML处理器感到困惑的保留字。 请尝试其他单词。

(根据Sarah Vessel的建议作为答案发布)。

我认为某些事情没有得到应有的更新。 我发现,如果我在SaveTemplateDialog窗口的NewTemplate属性中执行了以下操作,则我的TemplateDetail UserControl将正确填充我期望的所有数据:

public Template NewTemplate
{
    get
    {
        return (Template)GetValue(NewTemplateProperty);
    }
    set
    {
        SetValue(NewTemplateProperty, value);

        // The magic line, explicitly setting TemplateData property on
        // the TemplateDetails UserControl:
        uct_templateDetails.TemplateData = value;
    }
}

这使我相信,只是有下面SaveTemplateDialog的XAML是不够的,新的实例发送到TemplateDetails每当NewTemplate被更新:

<local:TemplateDetail HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                      TemplateData="{Binding Path=NewTemplate}" Grid.Row="2"
                      Grid.Column="1" Grid.ColumnSpan="3"
                      x:Name="uct_templateDetails"/>

我希望有人指出我在这里做错了什么,因为看来我不必明确地说uct_templateDetails.TemplateData = value; 每当SaveTemplateDialog.NewTemplate更改时。 我以为那是依赖项属性的关键所在,即更新它会导致使用它获取更新值的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM