WPF:绑定到依赖属性

5

我正在这里跟随一个教程,该教程展示了如何绑定到依赖属性的基本示例。

<Binding ElementName="This" Path="IPAddress" UpdateSourceTrigger="PropertyChanged">

其中"This"是当前窗口的名称:

<Window x:Class="SOTCBindingValidation.Window1" x:Name="This"

每当我尝试做这样的事情时,都会收到相同的错误信息: 无法找到绑定源 'ElementName=GridControlControl1'。BindingExpression:Path=IPAddress; DataItem=null; 目标元素是'TextBox' (Name='AddressBox');目标属性是'Text'(类型为'String') 我的代码:
 <UserControl x:Class="WpfGridtest.GridControl" x:Name="GridControlControl1" ... />
    <TextBox x:Name="AddressBox">
        <TextBox.Text>
            <Binding ElementName="GridControlControl1" Path="IPAddress" UpdateSourceTrigger="PropertyChanged">
        </Binding>
    </TextBox.Text>
</TextBox>

代码后台:

partial class GridControl : UserControl
     public static readonly DependencyProperty IPAddressProperty = DependencyProperty.Register("IPAddress", typeof(string), typeof(GridControl), new UIPropertyMetadata("1.1.1.1"));

        public string IPAddress
        {
            get { return (string)GetValue(IPAddressProperty); }
            set { SetValue(IPAddressProperty, value); }
        }

这就像是在 .Net 4.0 中发生了一些改变?


我刚刚重现了你所做的相同操作,似乎没有出现任何错误。 - Malcolm
你使用的是哪个框架? - Sonic Soul
好的,谢谢你确认这个有效。我的设置肯定有问题。 - Sonic Soul
2个回答

7
取决于您想要什么。我会尽量提供完整的答案。确保使用VS2010的XAML绑定生成器可以保证更好的成功,这也是我组装下面将要看到的语法的方法。 如果您想让UserControl的一个元素显示您的IPAddress依赖属性(在我的看来已经正确定义),请在UserControl标记的主体中使用以下语法:
   <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, 
                             AncestorType={x:Type my:GridControl}, 
                             AncestorLevel=1}, 
              Path=IPAddress}" />

大多数XAML绑定示例使用此语法,而不是更冗长的分层XML:
        <TextBlock>
            <TextBlock.Text>
                <Binding Path="IPAddress">
                    <Binding.RelativeSource>
                        <RelativeSource Mode="FindAncestor" 
                                        AncestorType="{x:Type my:GridControl}"
                                        AncestorLevel="1" 
                        />
                    </Binding.RelativeSource>
                </Binding>
            </TextBlock.Text>
        </TextBlock>

...但两种语法都可以产生相同的结果。请注意,AncestorType是您的UserControl的类名,而不是在其他标记中使用UserControl时提供的x:Name

假设您在UserControl之外的标记中有一个UI元素,并且您想要访问该元素的DependencyProperty。标记看起来像这样:

    <my:GridControl 
       x:Name="GridControl1" IPAddress="192.168.1.1" />
    <TextBox Text="{Binding ElementName=GridControl1, Path=IPAddress}"/>

或者,另一种选择是:
    <TextBox>
        <TextBox.Text>
            <Binding ElementName="GridControl1" Path="IPAddress"/>
        </TextBox.Text>
    </TextBox>

请注意,这一次您使用的是GridControl的x:Name属性而不是类名,并将其称为ElementName,而不是“Ancestor”。但在两种情况下,Path都是您定义的DependencyProperty的声明名称。


谢谢。虽然我和安德烈斯已经有了同样的东西,但我很感激你的帖子和XAML构建器链接。 - Sonic Soul
不客气。绑定语法很难;它只在运行时评估,而且错误几乎无法解释,我认为。除了我的一般回答之外,我所能想到的唯一一件事就是,在“Path=IPAddress”之后缺少一个右括号字符,但是XAML编辑器会立即捕捉到这个问题...还有,我使用了“FrameworkPropertyMetadata”而不是“UIPropertyMetadata”来设置DP,但我认为这也没有什么区别。 - Rob Perkins
这个答案对我非常有帮助。谢谢你。 - Mike Malter

3

尝试使用RelativeSource:

<TextBox>
  <TextBox.Text>
    <Binding Path="IPAddress">
      <Binding.RelativeSource>
        <RelativeSource
           Mode="FindAncestor"
           AncestorType="{x:Type UserControl}"
           AncestorLevel="1"
        />
      </Binding.RelativeSource>
    </Binding>
  </TextBox.Text>
</TextBox>

你可以在{x:Type UserControl}的位置插入你实际的类型,例如:

<TextBox>
  <TextBox.Text>
    <Binding Path="IPAddress">
      <Binding.RelativeSource>
        <RelativeSource xmlns:my="clr-namespace:WpfGridtest"
           Mode="FindAncestor"
           AncestorType="{x:Type my:GridControl}"
           AncestorLevel="1"
        />
      </Binding.RelativeSource>
    </Binding>
  </TextBox.Text>
</TextBox>

谢谢,我实际上在尝试了看起来所有可能的FindAncestor迭代之后才采用了DependecyProperty方法.. 确定是x:Type CustomControl。 - Sonic Soul
现在它工作了吗?或者使用FindAncestor方法有什么问题吗? - Andreas
我在FindAncestor上没有什么运气。周五我花了几个小时试图使用该方法,将其添加到顶部窗口以及控件,并引用x:Type。然而,我不断收到相同的无信息错误消息:“无法找到祖先blah blah”。 - Sonic Soul
等我晚些时候回家,我会尝试复现。在这里,我没有适当的集成开发环境(甚至没有时间)进行测试。我们真的应该能够完成这个... :) 不要放弃! - Andreas
我不能放弃!不管怎样都要完成我的项目 :) - Sonic Soul
应该是UserControl... 是因为太热了,原谅我。 - Andreas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接