2012-01-02 4 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

Ну а пара вещей выглядит немного странно, я не могу видеть настоящая проблема здесь. Что такое «public Employees EmployeesView = new Employees();» для? Почему это публично, когда у вас есть модель, которая является частной. Также я бы создал суперкласс для вашего измененного уведомления об изменении свойства. Свойство WorkSessions в viewmodel имеет установщик, но при его сбросе уведомления не возникают. удалите установщик или добавьте уведомление. Кроме того, я думаю, нам нужен какой-то код xaml. Но постарайтесь не публиковать все, что один пример, который не работает, должен быть достаточным. – dowhilefor

ответ

0

Я вижу несколько проблем с кодом:

  • Когда SelectedIndex обновляется, SelectedItem остается неизменным, и наоборот.
  • Похоже связывание ваших данных из заказа:

В DataContext собственность каскада вниз к каждому ребенку определенного объекта зависимостей.

код в конструкторе MainWindow, вероятно, следует заменить на:

this.DataContext = EmployeeViewModel; 

Затем в XAML установить остальные свойства с использованием связывания данных. Проблема в вашей ситуации заключается в том, что DataContext выбранного пользователя будет установлен только один раз. Это означает, что если вы выберете другого сотрудника, он не будет обновляться.

пример для вашей SelectedEmployee сетки:

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

Так что благодаря вам я, наконец, сумел заставить свои привязки работать. Кажется, что мой SelectedIndex не обновляется должным образом. Я могу легко перемещать элементы в DataGrid с помощью кнопок «<<" and ">>». Однако, когда я пытаюсь редактировать данные, устанавливаются только значения последнего элемента. http://imgur.com/VjP26 – CodePrimate

0

Одна из самых больших вещей, которые я вижу, это вы настройки свойства, не связывания их.

Например,

datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView; 

Вы говорите своему DataGrid, что это ItemsSource должен быть , что конкретный объект. Вам нужно привязать его к этому значению, чтобы вы сообщали его , вместо этого укажите. Это заставит ваш пользовательский интерфейс правильно отразить то, что находится в вашем ViewModel

Другой огромный красный флаг, который я вижу, - это ваш ViewModel, ссылающийся на что-то называемое и EmployeeView, что заставляет меня поверить, что ваш View и ViewModel слишком тесно связаны друг с другом. Ваш ViewModel должен содержать всю вашу бизнес-логику и код, в то время как представление обычно является XAML и просто отражает ViewModel удобным для пользователя способом.

The View и ViewModel никогда не должны непосредственно ссылаться друг на друга (я имел мой взгляд ссылки на мой ViewModel в некоторых редких случаях, но не наоборот)

Например, EmployeesViewModel может содержать

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

в то время как ваш View (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(); 
} 
Смежные вопросы