WPF DataBinding到DataGrid的列表-没有更新DataGrid

问题描述

我刚开始使用WPF进行编程,但遇到的问题是WPF中的数据网格不会更新值。我已经尝试了几天不同的尝试,但不幸的是最终没有任何效果。当将要启动GUI时,其自身的绑定确实起作用。我添加一个按钮以将新数据添加到数据网格。数据将在列表中更新,但不会在数据网格中更新。如果有人可以帮助我,那将非常好。

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        List<Person> list = new List<Person>();
        ObservableCollection<Person> obsCol = new ObservableCollection<Person>();

        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = this;           

            Person pers = new Person();
            pers.Name = "Tom";
            pers.Gender = "m";
            list.Add(pers);

            pers = new Person();
            pers.Name = "Bianca";
            pers.Gender = "w";
            list.Add(pers);

            obsCol = new ObservableCollection<Person>(list);

            grid.ItemsSource = obsCol;
        }

        private void Bt1_Click(object sender,RoutedEventArgs e)
        {
            Person pers = new Person();
            pers.Name = "Andreas";
            pers.Gender = "m";
            list.Add(pers);
            obsCol = new ObservableCollection<Person>(list);

            int u = 0;
        }
    }
}

Person.cs:

public class Person:INotifyPropertyChanged
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; onPropertyChanged(this,"Name"); }
    }

    private string gender;

    public string Gender
    {
        get { return gender; }
        set { gender = value; onPropertyChanged(this,"Gender"); }
    }

    // Declare the PropertyChanged event
    public event PropertyChangedEventHandler PropertyChanged;

    // OnPropertyChanged will raise the PropertyChanged event passing the
    // source property that is being updated.
    private void onPropertyChanged(object sender,string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(sender,new PropertyChangedEventArgs(propertyName));
        }
    }


}

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    List<Person> list = new List<Person>();
    ObservableCollection<Person> obsCol = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = this;           

        Person pers = new Person();
        pers.Name = "Tom";
        pers.Gender = "m";
        list.Add(pers);

        pers = new Person();
        pers.Name = "Bianca";
        pers.Gender = "w";
        list.Add(pers);

        obsCol = new ObservableCollection<Person>(list);

        grid.ItemsSource = obsCol;
    }

    private void Bt1_Click(object sender,RoutedEventArgs e)
    {
        Person pers = new Person();
        pers.Name = "Andreas";
        pers.Gender = "m";
        list.Add(pers);
        obsCol = new ObservableCollection<Person>(list);
    }
}

解决方法

在Bt1中_点击添加

grid.ItemsSource = obsCol;

最后

,

不创建新集合。而是将新的Person对象添加到现有对象中:

private void Bt1_Click(object sender,RoutedEventArgs e)
{
    var pers = new Person
    {
        Name = "Andreas",Gender = "m"
    };

    obsCol.Add(pers);
}

如果需要,在添加新数据之前先清除集合,

obsCol.Clear();

编辑:当然,您根本不需要list成员:

private readonly ObservableCollection<Person> obsCol
    = new ObservableCollection<Person>();

public MainWindow()
{
    InitializeComponent();

    DataContext = this; // this seems also pointless       

    grid.ItemsSource = obsCol;

    var pers = new Person
    {
        Name = "Tom",Gender = "m"
    };
    obsCol.Add(pers);

    pers = new Person
    {
        Name = "Bianca",Gender = "w"
    };
    obsCol.Add(pers);
}

仅当您具有对属性的绑定(如

)时,DataContext分配才有用
public ObservableCollection<Person> ObsCol { get; }
    = new ObservableCollection<Person>();

使用此XAML:

<DataGrid ItemsSource="{Binding ObsCol}" .../>
,

我强烈建议您将ViewModel与后台代码(MainWindow.xaml.cs)分开,并仅在其中初始化ViewModel。

我将在Xaml中进行绑定。因此,我的MainWindow.xaml看起来像这样:

<Window x:Class="WpfAppAddPerson.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel Grid.Row="0">
        <Button Content="add andreas" x:Name="ButtonAddAndreas" Click="ButtonAddAndreas_OnClick" Margin="5" Padding="5"/>
    </StackPanel>

    <DataGrid Grid.Row="1" ItemsSource="{Binding Persons}" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" Margin="10">

    </DataGrid>
</Grid>
</Window>

(MainWindow.xaml.cs)后面的代码:

using System.Windows;
namespace WpfAppAddPerson
{
    public partial class MainWindow : Window
    {
        private MainWindowViewModel _vm;

        public MainWindow()
        {
            InitializeComponent();

            _vm = new MainWindowViewModel();
            DataContext = _vm;
        }

        private void ButtonAddAndreas_OnClick(object sender,RoutedEventArgs e)
        {
            var p = new Person
            {
                Name = "Andreas",Gender = "m"
            };

            _vm.Persons.Add(p);

        }
    }
}

ViewModel(MainWindowViewModel.cs):

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using WpfAppAddPerson.Annotations;

namespace WpfAppAddPerson
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel()
        {
            Persons = new ObservableCollection<Person>();

            var p1 = new Person
            {
                Name = "Tom",Gender = "m"
            };

            Persons.Add(p1);

            var p2 = new Person
            {
                Name = "Bianca",Gender = "w"
            };

            Persons.Add(p2);
        }

        public ObservableCollection<Person> Persons { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }
    }
}

人类:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using WpfAppAddPerson.Annotations;

namespace WpfAppAddPerson
{
    public class Person : INotifyPropertyChanged
    {
        private string _name;
        private string _gender;

        public string Name
        {
            get => _name;
            set
            {
                _name = value;
                OnPropertyChanged();
            }
        }

        public string Gender
        {
            get => _gender;
            set { _gender = value; OnPropertyChanged(); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }
    }
}