无法理解WPF数据绑定

4

好的,我对编程和C#并不陌生,但似乎无法理解WPF数据绑定。我的同事们非常推崇它(是的,我也会向他们请教),但现在我却被难住了。

以下是我想要开始做的事情:

举个例子,我有一个像这样的东西列表:

List<Thing> thingList = Source.getList();

现在通常我会去

foreach(Thing t in thingList)
{
    //add thing to combobox
}

但我从中了解到,我可以通过数据绑定来填充下拉框,而不是直接操作。 我无法确定的是“thingList”应该放在哪里? 我要将它作为单独的属性吗?并且我应该把这个属性放在哪里? 我感到非常愚蠢,因为我已经苦苦挣扎了一段时间,但我找不到任何能让我理解这个 - 可能非常简单的 - 概念的例子。 有人愿意帮助我或指导我可能错过的逐步指南吗?

如果它与Winforms数据绑定类似,你的组合框应该有一个DataSource属性(或类似的东西),你应该能够设置comboBox.DataSource = Source.getList();只要你已经正确设置了DisplayMemberValueMembers,正确的内容将会显示,并且SelectedValue将检索对象本身。 - Chris Pfohl
以下是一些能帮助你朝着正确方向开始的 SO 问题: 将 WPF ComboBox 绑定到自定义列表MVVM: 从头到尾的教程 - Metro Smurf
在WPF中,像ComboBox和ListView这样的控件被用作数据的可视化容器。您可以在代码后台或从文件等位置构建和编辑列表,并将其绑定到表单上的控件。 - coldandtired
3个回答

2

使用 ObservableCollection<T> 绑定 WPF 数据。其中 T 是你的类。以下是示例:

public class NameList : ObservableCollection<PersonName>
{
    public NameList() : base()
    {
        Add(new PersonName("A", "E"));
        Add(new PersonName("B", "F"));
        Add(new PersonName("C", "G"));
        Add(new PersonName("D", "H"));
    }
  }

  public class PersonName
  {
      private string firstName;
      private string lastName;

      public PersonName(string first, string last)
      {
          this.firstName = first;
          this.lastName = last;
      }

      public string FirstName
      {
          get { return firstName; }
          set { firstName = value; }
      }

      public string LastName
      {
          get { return lastName; }
          set { lastName = value; }
      }
  }

现在在XAML中,转到资源标记。
<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:c="clr-namespace:SDKSample"

  x:Class="Sample.Window1"
  Width="400"
  Height="280"
  Title="MultiBinding Sample">

  <Window.Resources>
    <c:NameList x:Key="NameListData"/>
  </Window.Resources>


<ListBox Width="200"
         ItemsSource="{Binding Source={StaticResource NameListData}}"  // Name list data is declared in resource
         ItemTemplate="{StaticResource NameItemTemplate}"
         IsSynchronizedWithCurrentItem="True"/>

xmnls:c 将会给你选择类的选项。在这里,你可以选择 c、d、e 或者其他,但是请确保它应该在前面使用。


1
只有在预计集合会发生更改时,才需要使用ObservableCollection。 如果集合是静态的,则可以使用实现IEnumerable的任何内容。 - Metro Smurf
是的,我知道,当您需要双向绑定时,它将起作用,否则只需使用数据源和数据值成员等即可。 - user240141
这基本上是我在寻找的,是的。我知道这是一个非常广泛的主题,但你所描述的大多数都像我所想的“自动”过程。谢谢。 - Alex Crouzen

1

说到数据绑定,我发现如果仔细阅读这个页面,它可以回答大多数初学者对此的疑问。

回答问题:添加所有项目的替代方法是告诉ComboBox从哪里获取其项目,这是使用ItemsSource属性完成的。

您可以在XAML或代码中设置此属性,在XAML中需要绑定表达式,而在代码中则可以使用普通赋值:

comboBox.ItemsSource = thingList;

如果你没有进一步指定列表中那些对象应该如何显示,ToString 方法就会被调用,除非你覆盖了它,否则通常只会得到对象的类路径。有两种主要的方法可以告诉应用程序如何显示对象:
第一个也是更重的选项是使用 数据模板,用于使用控件显示复杂数据(这些控件又可以包含项和模板等)。第二种方法是使用轻量级属性,比如 DisplayMemberPath,它应该设置为应该显示的属性的名称(通常只是一个字符串)。
如果你的列表发生了变化,组合框应该自动更新源代码,所以源代码应该实现 INotifyCollectionChanged,在大多数情况下,你将使用标准实现 ObersableCollection<T>

0

大多数人会使用WPF数据绑定来填充组合框,但您不必这样做。

如果您愿意,可以通过代码添加项目。

很容易陷入按照“应该”完成所有事情的陷阱中,而没有充分的理由以那种方式进行操作(顺便说一句,我并不建议您手动添加项目,我只是说您可以这样做)。

List<Thing> thingList = Source.getList();

foreach(Thing t in thingList)
{
   combobox.Items.Add( t );
}

这可能是实现此目的最糟糕的方式,有很多不好的理由不要这样做。至少你应该更新你的示例,将集合分配给ItemsSource而不是逐个添加每个项。 - John Bowen
我认为我已经很清楚地表明了我并不推荐这种填充列表的方式。我只是在回应“但据我所知,我可以以某种方式不这样做”的说法。 - grantnz

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