【问题标题】:Replace current binding source object with another object用另一个对象替换当前绑定源对象
【发布时间】:2013-02-12 16:11:08
【问题描述】:

我对 C# 和 WPF 完全陌生,我正在努力在数据绑定方面做到最好。我有一个实现 INotifyPropertyChanged 的​​ MyClass;所以每次我更改属性值时,都会在我的 UI 中更新。然后我将堆栈面板的 DataContext 绑定到 MyClass 的对象。像这样:

<StackPanel Name="stackPanel1" DataContext="{Binding}">
        <TextBlock Name="textBlock1" Text="{Binding Path=Title, Mode=OneWay}" />
</StackPanel>

在后面的代码中我这样做:

item = new MyClass();
stackPanel1.DataContext = item;

并且绑定工作正常。如果我用另一个替换我当前的绑定源对象,我必须通过再次键入 datacontext 绑定来手动设置它:

item = new MyClass();
stackPanel1.DataContext = item;
item1 = new MyClass();
.
. //manipulate item1
.
if (item1 is ok)
   item=item1;
   stackPanel1.DataContext = item;

有没有更好的方法来替换我的源对象并更新所有关联的绑定?

【问题讨论】:

  • 首先,设置stackPanel1.DataContext = item1; 不是绑定。它只是设置一个属性。然后,XAML 中的DataContext="{Binding}" 没用,因为您在代码中设置了 DataContext。
  • I'm totally new to C# and WPF - 这些东西太多了,不能一起学习。在尝试在 WPF 中做任何事情之前,您最好先扎实 C#,做一些控制台应用程序,以便熟悉框架和语言,因为 WPF 本身是一个复杂的框架,不适合没有经验的开发人员。

标签: c# wpf data-binding


【解决方案1】:

当您说stackPanel1.DataContext = item; 时,您是在设置 属性,而不是绑定 它。

当您设置该属性时,您将其设置为等于对象的一个​​实例。当您绑定它时,您是在告诉它将从某个其他位置获取其值,因此请随时查看该位置以获取该值。

提供包含绑定属性的类实现 INotifyPropertyChanged,然后 UI 将在绑定属性更改时收到警报,这会导致重新评估绑定。

例如,如果您最初将DataContext 设置为

MyWindow.DataContext = this;

其中this 是您的Window,并且您的Window 有一个MyClass 类型的属性称为Item,那么您可以使用以下方法绑定DataContext

<StackPanel DataContext="{Binding Item}" ...>

无论何时您更新属性 Item,您的 StackPanel 的 DataContext 也会更新(前提是您实现了 INotifyPropertyChanged)。

如果您有兴趣,我喜欢在博客中介绍 WPF 中的初学者概念,您可能有兴趣查看我的文章 What is this "DataContext" you speak of?,该文章非常简单地解释了 DataContext 是什么以及如何使用它.

总而言之,WPF 有两层:UI 层和数据层。 DataContext 是数据层,当你写{Binding SomeProperty} 时,实际上是绑定到数据层。通常,您在后面的代码中设置一次数据层 (DataContext),然后在 XAML 中使用绑定使您的 UI 层显示来自数据层的信息。

(您可能也有兴趣查看我的Simple MVVM Example,其中包含一个非常简单的工作代码示例,并举例说明了INotifyPropertyChanged 的实现方式以及UI 层和数据层如何完全分离)

【讨论】:

    【解决方案2】:

    您可以在 MainWindow(或 UserControl 或其他任何内容)中添加 CurrentItem 属性,并为该属性实现 INotifyPropertyChange。然后设置

    DataContext = this;
    

    在 MainWindow 的构造函数中并像这样绑定:

    Text="{Binding Path=CurrentItem.Title}" 
    

    现在无论何时设置

    var item = new MyClass();
    ...
    CurrentItem = item;
    

    绑定将被更新。

    【讨论】:

      【解决方案3】:
      DataContext="{Binding}"
      

      stackPanel1.DataContext = item;
      

      两者的作用基本相同。不同之处在于一个是在 XAML 中完成的,另一个是在代码中完成的。虽然第一个示例允许在给定绑定父级的情况下更新绑定,但每次您想要更改堆栈面板附加到的内容时,都必须更新第二个示例。恕我直言,您应该创建一个通用的绑定父级来绑定。这将允许您更改子绑定,而不必每次都设置上下文。

      <StackPanel Name="parentPanel">
          <StackPanel Name="stackPanel1" DataContext="{Binding Path=Child}">
                  <TextBlock Name="textBlock1" Text="{Binding Path=Title, Mode=OneWay}" />
          </StackPanel>
      </StackPanel>
      
      
      parent = new ParentClass();
      parent.Child= new MyClass();
      parentPanel.DataContext = parent ;
      

      现在,如果在 ParentClass 上正确创建了 notify 属性更改,您可以更改子堆栈面板的绑定

      parent.Child= new NewClass();
      

      【讨论】:

        最近更新 更多