Привязки MVVM не работают должным образом - PullRequest
0 голосов
/ 02 января 2012

Обновление Удалось исправить проблему selectedIndex.Я также забыл установить SelectedItem и, естественно, это вызвало несколько проблем.

Итак, в 9 часов утра мы получили наше 24-часовое задание, и я столкнулся с кирпичной стеной.Предполагается, что мы создадим программу, которая позволит супервизору добавлять и удалять сотрудников и добавлять рабочие сессии, общее количество часов и общий доход.Но у меня возникли проблемы с успешной реализацией этого по MVVM-шаблону.По какой-то причине мои привязки просто не работают, и единственное решение, которое я вижу, - это кто-то просматривает мой проект и помогает мне устранить его.

Вот мой код - я очень сожалею о необходимости опубликоватьВсе дело, но, учитывая, что я понятия не имею, где проблема, я не видел никаких других вариантов.:

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;
    }
}

Ответы [ 2 ]

0 голосов
/ 04 января 2012

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

Например,

datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView;

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

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

View и ViewModel никогда не должны напрямую ссылаться друг на друга (в некоторых редких случаях у меня была ссылка View на мою 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();
}
0 голосов
/ 02 января 2012

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

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

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

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

this.DataContext = EmployeeViewModel;

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

Пример вашей сетки SelectedEmployee:

<Grid Name="grid_selectedEmployee" DataContext="{Binding SelectedEmployee, 
UpdateSourceTrigger=PropertyChanged}">...</Grid>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...