【问题标题】:How to use data binding in WPF C#?如何在 WPF C# 中使用数据绑定?
【发布时间】:2021-02-27 18:54:20
【问题描述】:

我想在 WPF 中将我的控件与我的视图模型绑定,并在我的数据库更新时自动更新数据控件。 我实现了一个具有一些List<myClass> 属性的视图模型,并从将保存在这些属性中的数据库接收数据。然后我将我的控件源绑定到这些属性。没关系,但是当我从数据库中获取新数据并将其保存在这些属性中时,控件数据不会更新。 如何以编程方式修复它?

这是我的代码:

public partial class MainWindow : Window
{
    ListOfPerson personList1 = new ListOfPerson();
    ListOfPerson personList2 = new ListOfPerson();
    

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        personList1.People.Add(new Person { PersonName = "test1" });
        personList2.People.Add(new Person { PersonName = "test2" });

        dg.AutoGenerateColumns = false;
        PropertyPath prop = new PropertyPath("PersonName");
        Binding bind = new Binding();
        bind.Mode = BindingMode.TwoWay;
        bind.Path = prop;
        dg.Columns.Add(new DataGridTextColumn { Header = "Name", Binding = bind });
        dg.ItemsSource = personList1.People;
    }
    public void Refresh()
    {
        personList1.People = personList2.People;
    }

    private void btn_Refresh_Click(object sender, RoutedEventArgs e)
    {
        Refresh();
    }
}
public class Person : INotifyPropertyChanged
{
    private string name;

    public Person()
    {
    }

    public Person(string value)
    {
        this.name = value;
    }

    public string PersonName
    {
        get { return name; }
        set
        {
            name = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
public class ListOfPerson : INotifyPropertyChanged
{
    private List<Person> people = new List<Person>();
    public List<Person> People
    {
        get
        {
            return people;
        }
        set
        {
            people = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

【问题讨论】:

  • 如果您打算在将元素分配给 ListOfPerson 的 People 属性后将元素添加到 List&lt;Person&gt;,您应该使用 ObservableCollection 而不是 List。
  • 坦克。但是我使用 Observable Collection,它也有这个问题。

标签: c# wpf binding code-behind


【解决方案1】:

您直接分配ItemsSource,这不是绑定

dg.ItemsSource = personList1.People;

然而,在 Refresh 上,您替换了 personList1People 集合。

personList1.People = personList2.People;

项目源仍然具有对旧集合的引用,因为您直接分配了它。您可以改为添加一个绑定,它会注意到项目源通过ListOfPerson 中的People 属性的属性更改通知实现进行了更改。这应该有效:

Binding itemsSourceBinding = new Binding
{
    Source = personList1,
    Path = new PropertyPath("People")
};
BindingOperations.SetBinding(dg, DataGrid.ItemsSourceProperty, itemsSourceBinding);

这只是处理这种情况的一种选择。另一种选择是仅使用 single ObservableCollection&lt;T&gt; Clear 并在两者之间再次填写或修改(如果您将其替换为 new instance 就像列表中的列表一样您的代码,您遇到与上述相同的问题)。它实现了INotifyCollectionChanged 接口并通知更改,例如自动添加、删除或插入项目,从而依次更新 UI。

【讨论】:

  • PropertyPath("personList1.People") 仅在 personList1 是公共属性时才有效。您可以将其用作 Source,使用 PropertyPath("People")
  • @Clemens 谢谢,你说得对,我忽略了人员列表实际上是字段。
  • Source = personList1.People 不会被 PropertyChanged 触发。
  • @thatguy 坦克。所以我需要为使用联合属性的应用程序中的每个控件创建新的绑定?我检查如果在personList1.People = personList2.People; 之后我使用dg.ItemsSource = personList1.People;,就可以了。但我想要不需要为每个控件实施的解决方案。我使用 INotifyCollectionChanged,但效果不佳。
  • @MaryamHeydari 如果没有绑定,属性更新将不起作用。当然,在这种情况下重新分配 ItemsSource 是可行的,因为您分配了列表的不同实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
相关资源
最近更新 更多