WPF绑定到属性列表未更新
本文关键字:更新 列表 属性 绑定 WPF | 更新日期: 2023-09-27 18:12:46
帮助。我已经用谷歌和stackoverflow搜索栏搜索了一个星期,但没有找到我的答案。
所以我有一个名为Student的类,属性是字符串Name、字符串Address、DoB出生日期和ListScore。以及Student类的ViewModel类。
public partial class StudentWindow : Window
{
public class DoB
{
public int Day { get; set; }
public int Month { get; set; }
public int Year { get; set; }
public DoB(int day, int month, int year)
{
Day = day;
Month = month;
Year = year;
}
public override string ToString()
{
return Day + "/" + Month + "/" + Year;
}
}
public class Student
{
public string Name { get; set; }
public string Address { get; set; }
public DoB DateOfBirth { get; set; }
public List<int> Score { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
private Student entry;
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string Property)
{
PropertyChanged(this, new PropertyChangedEventArgs(Property));
}
public string Name
{
get { return entry.Name; }
set { entry.Name = value; Notify("Name"); }
}
public string Address
{
get { return entry.Address; }
set { entry.Address = value; Notify("Address"); }
}
public string DateOfBirth
{
get { return entry.DateOfBirth.ToString(); }
set
{
var p = value.Split('/');
int d = 1, m = 1, y = 1;
bool pass = int.TryParse(p[0], out d) && int.TryParse(p[1], out m) && int.TryParse(p[2], out y);
if (pass)
{
entry.DateOfBirth = new DoB(d, m, y);
Notify("DateOfBirth");
}
else
throw new InvalidCastException();
}
}
public List<string> Score
{
get { return entry.Score.Select(sc => "" + sc).ToList(); }
set { entry.Score = value.Select(va => int.Parse(va)).ToList(); Notify("Score"); }
}
public ViewModel(Student entry)
{
this.entry = entry;
}
}
public ObservableCollection<ViewModel> entry { get; set; }
public StudentWindow()
{
InitializeComponent();
entry = new ObservableCollection<ViewModel>();
entry.Add(new ViewModel(new Student() { Name = "First People", Address = "Earth", DateOfBirth = new DoB(13, 11, 1996), Score = new List<int>(new int[] { 100, 90, 100, 90 }) }));
entry.Add(new ViewModel(new Student() { Name = "Second People", Address = "Moon", DateOfBirth = new DoB(13, 11, 1995), Score = new List<int>(new int[] { 90, 80, 100, 100 }) }));
DataContext = this;
}
}
XAML是
<Grid>
<DataGrid x:Name="dataGridStudent" ItemsSource="{Binding entry}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="210" Width="572"/>
<DataGrid x:Name="dataGridStudentScore" ItemsSource="{Binding ElementName=dataGrid, Path=SelectedItem.Score}" HorizontalAlignment="Left" Margin="10,242,0,0" VerticalAlignment="Top" Height="218" Width="572" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
dataGridStudent一切正常。
但dataGridStudentScore只显示值,无法编辑值。我必须将绑定路径设置为,否则将引发Path或Xpath异常。
请帮助您提供任何解决方案。我是这里的新手,请告诉我我的方法是否有问题。提前谢谢。
忽略对MVVM体系结构的混淆理解。学生成绩不可编辑的原因是您试图将值类型变量绑定到DataGridTextColumn。我不确定DependencyProperty绑定的后台实现,但我认为没有绑定到的引用来执行更新,因为它只是一个值类型变量。
我在wpf中也不是一个期望,但我会在下面实现同样的东西。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Score : ViewModelBase
{
public int Value { get; set; }
}
public class Student : ViewModelBase
{
public string Name { get; private set; }
public string Address { get; private set; }
public DateTime Dob { get; private set; }
public ObservableCollection<Score> Scores { get; set; }
public Student(string name, string address, DateTime dob)
{
Name = name;
Address = address;
Dob = dob;
Scores = new ObservableCollection<Score>();
}
}
public class StudentViewModel : ViewModelBase
{
public ObservableCollection<Student> Students { get; private set; }
public StudentViewModel()
{
Students = new ObservableCollection<Student>
{
new Student("Student A", "A Address", DateTime.Now)
{
Scores = new ObservableCollection<Score>
{
new Score { Value = 80 },
new Score { Value = 85 },
new Score { Value = 90 },
}
},
new Student("Student B", "B Address", DateTime.Now)
{
Scores = new ObservableCollection<Score>
{
new Score { Value = 70 },
new Score { Value = 75 },
new Score { Value = 60 },
}
}
};
}
private Student _selectedStudent;
public Student SelectedStudent
{
get { return _selectedStudent; }
set
{
_selectedStudent = value;
OnPropertyChanged("SelectedStudentScores");
}
}
public ObservableCollection<Score> SelectedStudentScores
{
get
{
if (_selectedStudent == null) return null;
return _selectedStudent.Scores;
}
}
public Score SelectedScore { get; set; }
}
<Window x:Class="StudentScoreWpfProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:studentScoreWpfProj="clr-namespace:StudentScoreWpfProj"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=studentScoreWpfProj:StudentViewModel,IsDesignTimeCreatable=True}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding Students}" AutoGenerateColumns="False"
SelectedItem="{Binding SelectedStudent}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=OneWay}" />
<DataGridTextColumn Header="Address" Binding="{Binding Address, Mode=OneWay}" />
<DataGridTextColumn Header="Birth" Binding="{Binding Dob, Mode=OneWay, StringFormat={}{0:MM/dd/yyyy}}" />
</DataGrid.Columns>
</DataGrid>
<DataGrid Grid.Row="1" ItemsSource="{Binding SelectedStudentScores}"
SelectedItem="{Binding SelectedScore}">
</DataGrid>
</Grid>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new StudentViewModel();
}
}