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异常。

请帮助您提供任何解决方案。我是这里的新手,请告诉我我的方法是否有问题。提前谢谢。

WPF绑定到属性列表未更新

忽略对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();
    }
}