0

В рамках MVVM разрабатываю приложение для базы данных SQlite. База состоит из таблиц: Orders(Id(Первичный ключ), Number, NameOfItem, Employee(ссылка на сотрудника из таблицы Staff)) Staff(Id(Первичный ключ), LastName, Name, MiddleName, DateofBirth, Gender, Unit)

На форме для добавления заказа(OrderWindow) необходимо сделать Combobox "Сотрудник" и вывести в него данные из таблицы Staff(для примера что угодно, хоть Id, хоть Name), чтобы выбранный элемент, в последствии, записывался в таблицу Order. Гуглил этот вопрос, но варианты решений рушат MVVM...

На данный момент есть один вариант, как вывести данные(фамилию) из таблицы Staff в comboBox: DataContext = new ViewModel(); и <ComboBox ItemsSource="{Binding Staffs}" DisplayMemberPath="LastName"/> для View OrderWindow, но тогда не выводятся значения выбранного элемента таблицы Order, а если же убрать DataContext = new ViewModel(); и оставить ` public Order Order { get; private set; }

    public OrderWindow(Order p)
    {
        InitializeComponent();
        Order = p;
        DataContext = Order;
        //DataContext = new ViewModel();
    }`

то данные из таблицы Order выводятся, но comboBox не заполняется элементами из Staff.

Может знает кто вариант решения проблемы? Так как основной код строился на основе статьи из Метанита (https://metanit.com/sharp/wpf/22.1.php)

ViewModel

{ public class ViewModel : INotifyPropertyChanged { ApplicationContext db; RelayCommand addCommand; RelayCommand editCommand; IEnumerable orders; RelayCommand addCommandStaff; RelayCommand editCommandStaff; IEnumerable staffs;

        public IEnumerable<Order> Orders
        {
            get { return orders; }
            set
            {
                orders = value;
                OnPropertyChanged("Orders");
            }
        }
    public IEnumerable&lt;Staff&gt; Staffs
    {
        get { return staffs; }
        set
        {
            staffs = value;
            OnPropertyChanged(&quot;Staffs&quot;);
        }
    }

    public ViewModel()
    {
        db = new ApplicationContext();
        db.Orders.Load();
        Orders = db.Orders.Local.ToBindingList();
        db.Staffs.Load();
        Staffs = db.Staffs.Local.ToBindingList();

    }

    public RelayCommand AddCommand
    {
        get
        {
            return addCommand ??
              (addCommand = new RelayCommand((o) =&gt;
              {
                  OrderWindow orderWindow = new OrderWindow(new Order());
                  if (orderWindow.ShowDialog() == true)
                  {
                      Order order = orderWindow.Order;
                      db.Orders.Add(order);
                      db.SaveChanges();
                  }
              }));
        }
    }      

    public RelayCommand EditCommand
    {
        get
        {
            return editCommand ??
              (editCommand = new RelayCommand((selectedItem) =&gt;
              {
                  if (selectedItem == null) return;
                  Order order = selectedItem as Order;

                  Order vm = new Order()
                  {
                      Id = order.Id,
                      Number = order.Number,
                      NameOfItem = order.NameOfItem,
                      Employee = order.Employee
                  };

                  OrderWindow orderWindow = new OrderWindow(vm);


                  if (orderWindow.ShowDialog() == true)
                  {
                      order = db.Orders.Find(orderWindow.Order.Id);
                      if (order != null)
                      {
                          order.Number = orderWindow.Order.Number;
                          order.NameOfItem = orderWindow.Order.NameOfItem;
                          order.Employee = orderWindow.Order.Employee;
                          db.Entry(order).State = EntityState.Modified;
                          db.SaveChanges();
                      }
                  }
              }));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string prop = &quot;&quot;)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

}

OrderWindow.cs

public partial class OrderWindow : Window
    {
        public Order Order { get; private set; }
        public Staff Staff1 { get; private set; }
    public OrderWindow(Order p)
    {
        InitializeComponent();
        Order = p;
        DataContext = Order;

        //DataContext = new ViewModel();
    }
}

Класс Order

public class Order : INotifyPropertyChanged
    {
    private int number;
    private string nameofitem;
    private string employee;

    public int Id { get; set; }

    public int Number
    {
        get { return number; }
        set
        {
            number = value;
            OnPropertyChanged(&quot;Number&quot;);
        }
    }

    public string NameOfItem
    {
        get { return nameofitem; }
        set
        {
            nameofitem = value;
            OnPropertyChanged(&quot;NameOfItem&quot;);
        }
    }
    public string Employee
    {
        get { return employee; }
        set
        {
            employee = value;
            OnPropertyChanged(&quot;Employee&quot;);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string prop = &quot;&quot;)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

Класс Staff

public class Staff : INotifyPropertyChanged
    {
        private string lastname;
        private string name;
        private string middlename;
        private DateTime dateofbirth;
        public enum gender
        {
            male = 1,
            female = 2,
        };
        private string unit;
    public int Id { get; set; }



    public string LastName
    {
        get { return lastname; }
        set
        {
            lastname = value;
            OnPropertyChanged(&quot;LastName&quot;);
        }
    }

    public string Name
    {
        get { return name; }
        set
        {
            name = value;
            OnPropertyChanged(&quot;Name&quot;);
        }
    }

    public string MiddleName
    {
        get { return middlename; }
        set
        {
            middlename = value;
            OnPropertyChanged(&quot;MiddleName&quot;);
        }
    }

    public DateTime DateOfBirth
    {
        get { return dateofbirth; }
        set
        {
            dateofbirth = value;
            OnPropertyChanged(&quot;DateOfBirth&quot;);
        }
    }

    private gender _gender;
    public gender Gender
    {
        get { return _gender; }
        set
        {
            _gender = value;
            OnPropertyChanged(&quot;Gender&quot;);
        }
    }

    public string Unit
    {
        get { return unit; }
        set
        {
            unit = value;
            OnPropertyChanged(&quot;Unit&quot;);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string prop = &quot;&quot;)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

OrderWindow.XAML

</Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="110" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Text="Номер" />
        <TextBlock Text="Название товара" Grid.Row="1" />
        <TextBlock Text="Сотрудник" Grid.Row="2" />
        <TextBlock Text="Тест" Grid.Row="3" />
    &lt;TextBox Text=&quot;{Binding Number}&quot; Grid.Column=&quot;1&quot; /&gt;
    &lt;TextBox Text=&quot;{Binding NameOfItem}&quot; Grid.Column=&quot;1&quot; Grid.Row=&quot;1&quot; /&gt;
    &lt;TextBox Text=&quot;{Binding Employee}&quot; Grid.Column=&quot;1&quot; Grid.Row=&quot;2&quot; /&gt;
    &lt;ComboBox ItemsSource=&quot;{Binding Staffs}&quot; DisplayMemberPath=&quot;LastName&quot;     Grid.Column=&quot;1&quot; Grid.Row=&quot;3&quot; /&gt;
    &lt;StackPanel HorizontalAlignment=&quot;Center&quot; Orientation=&quot;Horizontal&quot; Grid.Row=&quot;4&quot; Grid.Column=&quot;1&quot;&gt;
        &lt;Button IsDefault=&quot;True&quot; Click=&quot;Accept_Click&quot; MinWidth=&quot;60&quot; Margin=&quot;5&quot;&gt;OK&lt;/Button&gt;
        &lt;Button IsCancel=&quot;True&quot; MinWidth=&quot;60&quot; Margin=&quot;5&quot;&gt;Отмена&lt;/Button&gt;
    &lt;/StackPanel&gt;
&lt;/Grid&gt;

</Window>

  • тяжело понять, что вы делаете и в чем у вас проблема. Можете привести минимальный пример? – tym32167 Oct 16 '20 at 17:24
  • 1
    но тогда не выводятся значения выбранного элемента таблицы Order - ну, наверно потому, что источник данных, который вы задаете как DataContext (ViewModel), не содержит в себе Order (и его данные). Посмотрите еще раз, что вы делаете и как, не знаю, нарисуйте себе на листочке связи, что и где находится. Сейчас я думаю, что вы просто запутались. – EvgeniyZ Oct 16 '20 at 17:33
  • @tym32167 Добавил в исходное сообщение – Алексей Кузьмин Oct 16 '20 at 18:42
  • @EvgeniyZ Не исключено, но в том и дело, что связи отрисовал, как понял, и вроде как всё правильно, но... MVVM только изучаю, поэтому трудности... – Алексей Кузьмин Oct 16 '20 at 18:44
  • Xaml забыли, если говорите, что не показывает, то показывайте как привязываете и что. P.S. Вы же программист, не дублируйте код, зачем вам везде реализация INPC? – EvgeniyZ Oct 16 '20 at 18:46
  • @EvgeniyZ Добавил. Про INPC не учёл, спасибо) – Алексей Кузьмин Oct 16 '20 at 18:54
  • Ну и что вы там отрисовывали и проверяли? Binding Staffs - где свойство Staffs в Order? Почему оно должно отобразить то, чего нет? Ну и обратное, допустим Binding Employee, где свойство Employee в ViewModel? Вы уж определитесь, какие данные и как хотите отобразить. Также я заметил Click="Accept_Click" - по правилам MVVM это плохо, используйте команды. – EvgeniyZ Oct 16 '20 at 19:11
  • @EvgeniyZ Employee, NameOfItem и Number из Order, модель есть, во вью модели тоже есть обработка этого. А как можно объявить Staffs в Order? Я просто только недавно начал изучать всё это дело... Accept_Click в качестве кнопки OK, не знал, что это неправильно, учту) – Алексей Кузьмин Oct 16 '20 at 19:27
  • Staffs в Order - а какая у них связь? Вот допустим, есть "сотрудники", а также есть один заказ. Вы сейчас хотите в один заказ запихнуть список сотрудников, вопрос - зачем? Почему заказ знает про сотрудников? во вью модели тоже есть обработка этого - где в ViewModel (классе), эти свойства? Я вижу, например IEnumerable<Order> Orders - это как я понял список заказов, выводите его, далее берите то, что выбрано в отдельное свойство (или используйте IsSynchronizedWithCurrentItem), а от него уже привязывайтесь (прим: {Binding Prop.Number}) – EvgeniyZ Oct 16 '20 at 19:33
  • @EvgeniyZ Запихнуть одно в другое для окна добавления или редактирования заказа, чтобы выбирать сотрудника из списка и вносить его в БД для таблицы Order. Ох, попробую) Спасибо большое! – Алексей Кузьмин Oct 16 '20 at 19:45
  • Запихнуть одно в другое для окна добавления или редактирования заказа - но тем самым вы нарушаете кучу других правил программирования, например S из SOLID, которое говорит о единой ответственности ваших сущностей. Ваш класс заказа должен содержать лишь ссылку на сотрудника (Staff), не сам список всех сотрудников. А вот окно редактирования, должно уже эти данные подгружать из разных мест и выводить пользователю для выбора. Как я уже говорил выше, просто сделайте классы, которые будут отвечать за что-то одно и дальше хоть на листочке их свяжите друг с другом, посмотрите как лучше делать. – EvgeniyZ Oct 16 '20 at 19:50

0 Answers0