WPF依赖属性

6

我刚刚意识到我一直在强制绑定/依赖属性,但并没有真正理解这个概念。

下面是依赖属性:

public string Problem
{
    get { return (string)GetValue(ProblemProperty); }
    set { SetValue(ProblemProperty, value); }
}

public static readonly DependencyProperty ProblemProperty =
    DependencyProperty.Register(
    "Problem",
    typeof(string),
    typeof(TextBox));

XAML如下所示:
<TextBlock Text="{Binding Path=Problem}"/>

我在对象的构造函数中手动设置Problem属性的值,但它不会相应地更新TextBlock。有什么想法吗?我尝试了绑定中的Mode="OneWay"Mode="TwoWay",但仍然无法工作。

我以为这应该自动工作的?或者我基本上是在犯错?

谢谢


我这边看起来一切正常。问题可能出在您的“DataContext”上。您是怎么设置它的? - Kent Boogaart
6个回答

11
您遇到的问题与您的DataContext相关。 {Binding}扩展需要知道您要绑定的属性所在的位置。它默认查看的位置是元素的DataContext,这个DataContext默认情况下始终设置为其父元素的DataContext。如果您将DataContext沿着逻辑树向上移动到父窗口,则DataContext将为null(因为您窗口的DataContext为null)。因此,您的textblock上的{Binding}表示“将我的Text属性绑定到我的DataContext的Problem属性...这个属性为null。”
有几种方法可以解决这个问题。一个方法就像Jobi提到的那样,将您的绑定的Element属性设置为指向定义DependencyProperty的Window,如下所示:
<TextBlock Text="{Binding Path=Problem,ElementName=_window}" />

另一个选择是将窗口的DataContext设置为指向其自身,这样其内容中包含的所有元素都将具有窗口的DataContext。

<Window ....
        DataContext="{Binding RelativeSource={RelativeSource Self}}">

现在,每当您需要绑定到在窗口中定义的属性(例如您的Problem依赖属性)时,只需执行以下操作:

<TextBlock Text="{Binding Problem}" />

将窗口的数据上下文设置为自身并不适用于我。只有当我将一个元素的数据上下文设置为窗口的下一级或更多级别时(第一个网格有效),它才能正常工作。这是预期的吗? - Erik83

2

尝试使用typeof(object)而不是typeof(string)


2
您可以在此处使用元素名称绑定,该元素将是窗口本身。
<Window x:Class="WpfToolTip.Window1"
x:Name="_window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Button Click="OnClick" Content="OK" />
        <Button Click="OnCancel" Content="Cancel" />
        <TextBlock Text="{Binding Path=Problem,ElementName=_window}" />
</StackPanel>


0

了解您所描述的问题的原因有两种方法。

首先 - 您应该尝试设置属性更改处理程序(在依赖属性声明中),并在那里设置断点。您将看到您的属性是否正在更改。

其次 - 您应该检查依赖属性所有者的类型。

请问能否展示完整的XAML和CodeBehind代码?


0

在您的代码中,您为TextBox类注册了Dependency Property(引用的最后一行)。

public static readonly DependencyProperty ProblemProperty =
DependencyProperty.Register(
"Problem",
typeof(string),
typeof(TextBox));

因此,您只能为文本框设置ProblemProperty的值,但我在任何代码片段中都找不到任何文本框。 您应该为将分配值的类型注册依赖属性,在您的示例中,正确的选择对我来说并不明显。 您可以像Micah一样将其定义为窗口的DP,然后在实例化的窗口上设置属性。或者您可以将其定义为窗口内的任何命名依赖对象,即某个名称为m_ContentElement的对象,然后将绑定设置为
{Binding ElementName=m_ContentElement, Path=Problem}
或更短:
{Binding Problem, ElementName=m_ContentElement}


0

这是设置在窗口中的。

public partial class Window1 : Window
{
    public string Problem
    {
        get { return (string)GetValue(ProblemProperty); }
        set { SetValue(ProblemProperty, value); }
    }

    public static readonly DependencyProperty ProblemProperty =
                    DependencyProperty.Register(
                    "Problem",
                    typeof(string),
                    typeof(Window1));


    public Window1()
    {
        InitializeComponent();

        Problem = "ifowiof";
    }

    public void OnClick(object sender, EventArgs e)
    {
        Problem = "behl";
    }

    public void OnCancel(object sender, EventArgs e)
    {
       Problem = "eioeopje";
    }
}

XAML:

<Window x:Class="WpfToolTip.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <StackPanel>
            <Button Click="OnClick" Content="OK" />
            <Button Click="OnCancel" Content="Cancel" />
            <TextBlock Text="{Binding Path=Problem}" />
    </StackPanel>
</Window>

如果我在加载时按照您所说的设置RelativeSource,它可以工作,但是如果我手动更改代码中的Problem属性(例如通过按钮单击),它永远不会使用新值更新TextBlock


你有没有找到这个问题的答案?我也遇到了类似的问题。当您设置问题属性时,似乎绑定会丢失。我不确定使用这种方法更新值的正确流程是什么。 - David Turvey

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