WPF数据绑定混淆

4

我刚开始学习有关WPF的课程,对于与数据绑定相关的一些领域感到有些困惑。我的语法没有问题,但很可能犯了一些新手错误,因此我有几个问题。

我做了一个简单的屏幕,其中有2个文本框,当我点击按钮时,这两个项目将添加到一个ListBox中。

XAML的Window标签内引用People类。

 xmlns:classes="clr-namespace:WPF_Course.Classes"

新增了一个窗口资源

<Window.Resources>
        <classes:People x:Key="people"/>
</Window.Resources>

以下是我如何声明ListBox:

<ListBox DataContext="{Binding Source={StaticResource people}}"
                 ItemsSource="{Binding Persons}"
                 x:Name="PersonListBox">

            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <StackPanel>
                            <TextBlock Text="{Binding FullName}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>

            </ListBox.ItemTemplate>                
</ListBox>

所以,我已经向我的ListBox添加了一个DataContext,在那里绑定到我的people资源,并且我添加了一个ItemSource,其中查找我的People中的属性。
这是我的类。
public class People : ObservableCollection<Person> 
    {
        public ObservableCollection<Person> Persons { get { return persons; } set { persons = value; } }
        private ObservableCollection<Person> persons = new ObservableCollection<Person>();

        public People()
        {
            for (int i = 0; i < 1; i++)
            {
                // implicitly I add one item just for messing around with the constructor
                Persons.Add(new Person()
                {
                    Name = "Dummy",
                    LastName = "Dummy",
                    Age = 15
                });
            }
        }
    }

根据我目前的工作,我有以下问题:
1)(它们有相同的效果,但是它们背后的推理不同是什么区别?)的区别是什么?
ItemsSource = "{Binding Persons}"

并且

ItemsSource = "{Binding Path = Persons }"

同时,如果我将 ItemSource = "{Binding}" 留空,那么我是不是实例化了一个 People 实例,因此所有的逻辑都从该类的构造函数中处理?我已经试过了,似乎确实如此,但我不确定。
2)在我的 People 类中,我已经实现了 ObservableCollection<Person>(其中 Person 也是一个类)。最初,我是从构造函数本身对列表进行静态添加的,并且没有在类内定义属性(ObservableCollection<person> type 类型的属性),因此需要它(接口的实现),但现在使用属性,我真的需要它吗?所以我的问题是:
如果我的类唯一的目的是仅从构造函数中加载其集合中的内容(而不是来自外部类,因此需要某种属性),那么将我的类与 ObservableCollection<myClass> 结合使用是最佳实践,还是像我所做的那样定义相同类型的属性?(用于从外部类访问)
非常抱歉,我的问题听起来有些愚蠢,我正在寻求验证,因为我最近才开始使用 wpf。
谢谢
 ObservableCollection<Person> ppl;
    public MainWindow()
        {
            InitializeComponent();
            person = new Person();
            stackPanelPerson.DataContext = person;

            people = new People();
            ppl = people.Persons;
            PersonListBox.ItemsSource = ppl;
        }

一开始我是这样做的。
 ppl.Add(new Person() { Name = boxFirstName.Text, LastName = boxLastName.Text, Age = Int32.Parse(boxAge.Text) });

后来我意识到我在我的Person类(INotifyPropertyChanged)上使用了数据绑定,所以我将其更改为:

 ppl.Add(new Person() { Name = person.Name, LastName = person.LastName, Age = person.Age});

感谢大家的回复!再次致以感谢!祝你们有美好的一天!
4个回答

4

问题1:

没有区别。 {Binding xyz}{Binding Path=xyz} 是相同的,它几乎像是一个快捷方式。但它只能用于你在绑定中第一次写的东西,例如,你不能这样做:

{Binding ElementName=myElement, xyz}

相反,你应该这样做:
{Binding ElementName=myElement, Path=xyz}

甚至更好的是:
{Binding xyz, ElementName=myElement}

这里 有一个相关的问题。

第二个问题:

你所做的是正确的,你的人员集合应该被公开为一个 Property,为什么?因为这样你就可以绑定它了。

在这种情况下不需要静态属性。

我强烈建议研究 MVVM 设计模式。你可以在这里找到教程。


2

1)许多标记扩展都能理解缩短语法,{Binding Persons}{Binding Path=Persons}之间没有区别。但是,有时您必须使用完整的语法。

一个例子是制作自己的

public class ExceptionBinding : Binding
{
    public ExceptionBinding()
    {
        ValidationRules.Add(new ExceptionValidationRule());
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    }
}

那么,您必须使用完整的语法{l:ExceptionBinding Path=Persons}

2)这取决于情况。如果集合在绑定后不会改变则不必使用ObservableCollection<>。创建List<>,填充它,然后再绑定它会很好地工作。

您需要了解MVVM,因为使用它将简化使用场景并使许多事情更加清晰。


好的答案,就像迈克的一样...我认为所有这些都从不同的角度阐明了你的问题 :) - Noctis

1

迈克已经讲了我想说的内容...

除了绑定,你还可以在绑定中显示不同的东西。这是我为代码项目编写的教程: 理解SelectedValue、SelectedValuePath、SelectedItem & DisplayMemberPath + 演示

你可以使用虚拟数据对类进行模拟,这样你就可以在VS的XAML设计器中预览了。MVVM light框架也很有帮助,而且还有一些很酷的功能。还有其他框架,但你并不真正需要一个来做MVVM,它们只是有所帮助。

除此之外,祝你好运... :) 一旦你掌握了它,它会变得很有趣...


-3
  1. 没有区别。 {Binding propertyName}{Binding Path=propertyName} 是一样的,它几乎像是一个快捷方式,但是构造函数会因为 DataContext="{Binding Source={StaticResource people}}" 被调用。

  2. 这取决于情况。如果绑定后集合不会改变,那么您不必使用 ObservableCollection<>。创建 List<>,填充它,然后绑定到它将非常有效。但是,如果您想要从屏幕更改集合并更新列表,则需要使用 ObservableCollection<>


抄袭他人的答案? - Sybren

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