问题描述
我刚开始使用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));
}
}
}