2015-09-14 66 views
0

幫助。我一直在尋找谷歌和stackoverflow搜索欄一個星期,沒有找到我的答案。WPF綁定到屬性列表不更新

所以我有一個名爲學生類,屬性是字符串名稱,字符串地址,DoB DateofBirth和列表得分。以及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異常。

請幫助你有任何解決方案。我是新手,請告訴我的方法是否有問題。提前致謝。

+0

使用DataTemplate中,而不是datagridTextColumn – Sajeetharan

+0

「請你告訴我們,如果事情是錯我的方法」 - 你殺了MVVM。 「entry = new ObservableCollection ();」 - 不不不。請先學習基本的MVVM。 – niksofteng

回答

0

忽略了對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(); 
    } 
} 
+0

Omg !!你是搖滾樂隊!我測試了它並且工作!現在我有更好的理解。謝謝非常,你是非常有幫助的:D 順便說一句,你爲什麼讓財產私人設置?這樣我就不能修改名稱和地址。是否有理由將其設置爲私人? – Darmawan

+0

只是沒想到名稱或地址是可編輯的。 您可以將其重新設置爲公開狀態,以使其可用於GUI – cscmh99