2012-01-02 72 views
0

更新 管理修復selectedIndex問題。我忘了設置SelectedItem以及自然導致一些問題。MVVM綁定無法正常工作

因此,今天早上9點,我們得到了24小時的任務,並且撞到了一堵磚牆。 我們應該創建一個程序,允許主管添加和刪除員工並添加工作會話,總小時數和總收入。但是我有一些問題在MVVM-Pattern之後成功實現。出於某種原因,我的Bindings根本無法正常工作,唯一可以看到的解決方案是有人在查看我的項目並幫助我排除故障。

這是我的代碼 - 我很抱歉不得不發佈整個事情,但鑑於我不知道問題出在哪裏,我沒有看到任何其他選項。 :

EmployeeModel

[Serializable] 
public class WorkSessions : ObservableCollection<WorkSessionModel> 
{ 
    public WorkSessions() 
    { 

    } 
} 
[Serializable] 
public class WorkSessionModel : INotifyPropertyChanged 
{ 
    private DateTime _dateTime; 
    private string _id; 
    private double _hours; 

    public WorkSessionModel() 
    { 

    } 

    public DateTime DateTime 
    { 
     get { return _dateTime; } 
     set 
     { 
      _dateTime = value; 
      NotifyPropertyChanged("DateTime"); 
     } 
    } 

    public string ID 
    { 
     get { return _id; } 
     set 
     { 
      _id = value; 
      NotifyPropertyChanged("ID"); 
     } 
    } 
    public double Hours 
    { 
     get { return _hours; } 
     set 
     { 
      _hours = value; 
      NotifyPropertyChanged("Hours"); 
      NotifyPropertyChanged("TotalHours"); 
     } 
    } 


    [field: NonSerialized] 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

WorkSessionModel

[Serializable] 
public class WorkSessions : ObservableCollection<WorkSessionModel> 
{ 
    public WorkSessions() 
    { 

    } 
} 
[Serializable] 
public class WorkSessionModel : INotifyPropertyChanged 
{ 
    private DateTime _dateTime; 
    private string _id; 
    private double _hours; 

    public WorkSessionModel() 
    { 

    } 

    public DateTime DateTime 
    { 
     get { return _dateTime; } 
     set 
     { 
      _dateTime = value; 
      NotifyPropertyChanged("DateTime"); 
     } 
    } 

    public string ID 
    { 
     get { return _id; } 
     set 
     { 
      _id = value; 
      NotifyPropertyChanged("ID"); 
     } 
    } 
    public double Hours 
    { 
     get { return _hours; } 
     set 
     { 
      _hours = value; 
      NotifyPropertyChanged("Hours"); 
      NotifyPropertyChanged("TotalHours"); 
     } 
    } 


    [field: NonSerialized] 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

EmployeeViewModel

public class EmployeeViewModel : ViewModelBase 
{ 
    private Employees _employeesModel = new Employees(); 
    public Employees EmployeesView = new Employees(); 

    public ObservableCollection<WorkSessionModel> WorkSessions { get; set; } 

    private string _id = "0"; 
    private string _name = "noname"; 
    private double _wage = 0; 
    private int _totalhours = 0; 
    public string ID 
    { 
     get { return _id; } 
     set { _id = value; RaisePropertyChanged("ID"); } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      _name = value; 
      RaisePropertyChanged("Name"); 
     } 
    } 
    public double Wage 
    { 
     get { return _wage; } 
     set 
     { 
      _wage = value; 
      RaisePropertyChanged("Wage"); 
     } 
    } 
    public int TotalHours 
    { 
     get { return _totalhours; } 
     set 
     { 
      _totalhours = value; 
      RaisePropertyChanged("TotalHours"); 
     } 
    } 

    private EmployeeModel _selectedEmployee = new EmployeeModel(); 
    public EmployeeModel SelectedEmployee 
    { 
     get { return _selectedEmployee; } 
     set 
     { 
      _selectedEmployee = value; 
      RaisePropertyChanged("SelectedEmployee"); 
     } 
    } 

    private int _selectedEmployeeIndex; 
    public int SelectedEmployeeIndex 
    { 
     get { return _selectedEmployeeIndex; } 
     set 
     { 
      _selectedEmployeeIndex = value; 
      RaisePropertyChanged("SelectedEmployeeIndex"); 
     } 
    } 

    #region RelayCommands 

    // Employee Relay Commands 
    public RelayCommand EmployeeAddNewCommand { set; get; } 
    public RelayCommand EmployeeDeleteCommand { set; get; } 
    public RelayCommand EmployeeNextCommand { set; get; } 
    public RelayCommand EmployeePrevCommand { set; get; } 
    public RelayCommand EmployeeTotalHoursCommand { get; set; } 

    #endregion 

    public EmployeeViewModel() 
    { 
     InitCommands(); 
    } 

    private void InitCommands() 
    {   
     EmployeeAddNewCommand = new RelayCommand(EmployeeAddNewExecute, EmployeeAddNewCanExecute); 
     EmployeeDeleteCommand = new RelayCommand(EmployeeDeleteNewExecute, EmployeeDeleteCanExecute); 
     EmployeeNextCommand = new RelayCommand(EmployeeNextExecute, EmployeeNextCanExecute); 
     EmployeePrevCommand = new RelayCommand(EmployeePrevExecute, EmployeePrevCanExecute); 
     //EmployeeTotalHoursCommand = new RelayCommand(EmployeeTotalHoursExecute, EmployeeTotalHoursCanExecute); 
    } 

    //private void EmployeeTotalHoursExecute() 
    //{ 
    // _selectedEmployee.TotalHours(); 
    //} 

    //private bool EmployeeTotalHoursCanExecute() 
    //{ 
    // return true; 
    //} 

    private void EmployeeAddNewExecute() 
    { 
     EmployeeModel newEmployee = new EmployeeModel(); 
     EmployeesView.Add(newEmployee); 
     _employeesModel.Add(newEmployee); 
     SelectedEmployee = newEmployee; 
    } 

    private bool EmployeeAddNewCanExecute() 
    { 
     return true; 
    } 

    private void EmployeeDeleteNewExecute() 
    { 
     if (MessageBox.Show("You are about delete all submissions for  Employee," + SelectedEmployee.Name + "(" + SelectedEmployee.ID +")\r\nAre you sure?", "This is a Warning!", MessageBoxButton.YesNo) == MessageBoxResult.Yes) 
     { 
      _employeesModel.Remove(SelectedEmployee); 
      EmployeesView.Remove(SelectedEmployee); 
     } 
    } 

    private bool EmployeeDeleteCanExecute() 
    { 
     if (SelectedEmployee != null) 
      return true; 
     else return false; 
    } 

    private void EmployeeNextExecute() 
    { 
     SelectedEmployeeIndex++; 
    } 
    private bool EmployeeNextCanExecute() 
    { 
     if (SelectedEmployeeIndex < EmployeesView.Count - 1) 
      return true; 
     return false; 
    } 

    private void EmployeePrevExecute() 
    { 
     SelectedEmployeeIndex--; 
    } 
    private bool EmployeePrevCanExecute() 
    { 
     if (SelectedEmployeeIndex > 0) 
      return true; 
     return false; 
    } 
} 

查看

public partial class MainWindow : Window 
{ 
    public EmployeeViewModel EmployeeViewModel = new EmployeeViewModel(); 

    public MainWindow() 
    { 
     InitializeComponent(); 

     menu_employee.DataContext = EmployeeViewModel; 
     sp_employees.DataContext = EmployeeViewModel; 
     datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView; 
     grid_selectedEmployee.DataContext = EmployeeViewModel.SelectedEmployee; 
    } 
} 
+1

好,而一對夫婦的事情看起來有點怪怪的,我看不到這是一個真正的問題。什麼是「公務員EmployeesView =新員工()」;「對於?爲什麼它是公開的,當你有一個私人模型。另外我會爲你的財產更改通知創建一個超類。 ViewModel中的WorkSessions屬性具有setter,但重置時不會引發通知。刪除setter或添加通知。除此之外,我認爲我們需要一些xaml代碼。但儘量不要發佈一個不工作的例子就足夠了。 – dowhilefor 2012-01-02 13:30:30

回答

0

我可以看到一些問題與您的代碼:

  • 當selectedIndex被更新的,則selectedItem保持不變,反之亦然。
  • 它看起來像你的數據綁定失靈:

DataContext財產級聯降到一定的依賴對象的每一個孩子。

this.DataContext = EmployeeViewModel; 

然後在XAML中設置使用數據綁定屬性的其餘部分:

在主窗口的構造函數的代碼應該可能被替換。在你的情況下,問題是選擇員工的DataContext只設置一次。這意味着如果您選擇另一位員工,則不會更新。

一個例子爲您SelectedEmployee格:

<Grid Name="grid_selectedEmployee" DataContext="{Binding SelectedEmployee, 
UpdateSourceTrigger=PropertyChanged}">...</Grid> 
+0

謝謝你,我終於設法讓我的綁定工作..有點。看來我的SelectedIndex沒有正確更新。我可以使用「<<" and ">>」按鈕來遍歷DataGrid中的項目。但是,當我嘗試編輯數據時,只有最後一項的值正在設置。 http://imgur.com/VjP26 – CodePrimate 2012-01-02 14:29:06

0

其中一個最大的事情,我看到的是你設置性質,不結合他們。

例如,

datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView; 

你告訴你的DataGrid,它的的ItemsSource應該特定對象。你需要將它綁定到該值,所以你告訴它指向那個屬性。這將使你的UI正確反映你的ViewModel中的內容

我看到的另一個巨大的紅旗是你的ViewModel引用了一些叫做EmployeeView的引用我認爲你的View和ViewModel過於緊密聯繫在一起的東西。 您的ViewModel應該包含您的所有業務邏輯和代碼,而View通常是XAML,並且只是以一種用戶友好的方式反映了ViewModel。

觀與視圖模型不應該直接引用對方(我有我的觀看基準我的ViewModel在某些罕見的情況,但從來沒有周圍的其他方式)

例如,EmployeesViewModel可能包含

  • ObservableCollection<Employee> Employees
  • Employee SelectedEmployee
  • ICommand AddEmployeeCommand
  • ICommand DeleteEmployeeCommand

,而你的視圖(XAML)可能是這樣的:

<StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <Button Content="Add" Command="{Binding AddEmployeeCommand}" /> 
     <Button Content="Delete" Command="{Binding DeleteEmployeeCommand}" /> 
    </StackPanel> 

    <DataGrid ItemsSource="{Binding Employees}" 
       SelectedItem="{Binding SelectedEmployee}"> 
     ... etc 
    </DataGrid> 

    <UniformGrid DataContext="{Binding SelectedEmployee}" Columns="2" Rows="4"> 
     <TextBlock Text="ID" /> 
     <TextBox Text="{Binding Id}" /> 
     ... etc 
    </UniformGrid > 
</StackPanel> 

,你應該設置的唯一的事情是整個窗口的DataContext的。通常我覆蓋App.OnStartup()啓動我的應用程序:

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 

     var view = new MainWindow(); 
     var vm = new EmployeesViewModel; 
     view.DataContext = vm; 
     view.Show(); 
    } 
} 

雖然我在你的情況想這也將工作:

public MainWindow() 
{ 
    InitializeComponent(); 

    this.DataContext = new EmployeesViewModel(); 
} 
相關問題