简体   繁体   English

WPF绑定到属性列表未更新

[英]WPF Binding to property list not updating

Help. 救命。 I've been searching with google and stackoverflow searchbar for a week and didn't found my answers. 我已经使用Google和stackoverflow搜索栏搜索了一周,却没有找到答案。

So I have a class named Student and the properties is string Name, string Address, DoB DateofBirth, and List Score. 因此,我有一个名为Student的类,其属性为字符串名称,字符串地址,DoB DateofBirth和列表得分。 And a ViewModel class for the Student class. 还有一个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;
    }
}

And the XAML is 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>

Everything works fine for dataGridStudent. 对于dataGridStudent一切正常。

But dataGridStudentScore is only displaying the values and unable to edit the value. 但是dataGridStudentScore仅显示值,而无法编辑值。 I have to set the Binding Path=. 我必须设置Binding Path =。 , otherwise the Path or Xpath exception will thrown. ,否则会抛出Path或Xpath异常。

Please help with any solutions you have. 请为您提供任何解决方案的帮助。 I'm newbie here, please do tell if something is wrong with my approach. 我是新手,请告诉我我的做法是否有问题。 Thanks in advance. 提前致谢。

Ignoring the confusing understanding on the MVVM architecture. 忽略对MVVM体系结构的困惑理解。 The reason student score not editable is that you try to bind a value type variable to DataGridTextColumn. 学生分数不可编辑的原因是您尝试将值类型变量绑定到DataGridTextColumn。 I'm not sure about the background implementation of DependencyProperty binding but I would imagine there is no reference to bind to in order to perform the update as it's just a value type variable. 我不确定DependencyProperty绑定的后台实现,但是我可以想象没有引用可以绑定到该更新中,因为它只是一个值类型变量。

I'm not an expect in wpf too but I would implement that same thing in the following. 我对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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM