Хобрук: Ваш путь к мастерству в программировании

WPF MVVM DataGrid заполняется запросом во время выполнения

Будучи новичком в WPF и MVVM, я последние несколько дней пытался решить эту проблему. Я искал помощь по всему stackoverflow и google/youtube.

У меня есть DataGrid (biound из OrderListView), который заполняется из BindableCollection (Caliburn Micro) модели. Однако мне нужно ввести свойство («Программа») связанных данных из другого BindableCollection ProductList (обе коллекции имеют общее свойство «Код».

По сути, я хочу, чтобы DataGrid отображал все столбцы на основе OrderModel и заполнял столбец Programs соответствующими данными из коллекции Products только во время выполнения.

OrderModel.cs

public class OrderModel : BaseModel
    {
        private DateTime _orderDate;
        public DateTime OrderDate
        {
            get { return _orderDate; }
            set { _orderDate = value; OnPropertyChanged(); }
        }

        private string _code;
        public string Code
        {
            get { return _code; }
            set { _code = value; OnPropertyChanged(); }
        }

        private int _qty;
        public int Qty
        {
            get { return _qty; }
            set { _qty = value; OnPropertyChanged(); }
        }

ProductModel.cs

public class ProductModel : BaseModel
    {
        private string _code;
        public string Code
        {
            get { return _code; }
            set { _code = value; OnPropertyChanged(); }
        }

        private int _program;
        public int Program
        {
            get { return _program; }
            set { _program = value; OnPropertyChanged(); }
        }

DataGrid в OrderView.xaml

<DataGrid ItemsSource="{Binding OrderListView}" AutoGenerateColumns="False">
                <DataGrid.Columns>

                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Code}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Qty}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Program}"/>  <- This from ProductList ??
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

                </DataGrid.Columns>
            </DataGrid>

OrderViewModel.cs

public class OrderViewModel : Screen
{
        private readonly IDataConnection _connect;

        private ICollectionView _orderView;
        public ICollectionView OrderListView
        {
            get => _orderView;
            set
            {
                _orderView = value;
                NotifyOfPropertyChange(() => OrderListView);
            }
        }

        private BindableCollection<OrderModel> _orderList;
        public BindableCollection<OrderModel> OrderList
        {
            get => _orderList;
            set
            {
                _orderList = value;
                NotifyOfPropertyChange(() => OrderList);
            }
        }

        private BindableCollection<ProductModel> _productList;
        public BindableCollection<ProductModel> ProductList
        {
            get { return _productList; }
            set { _productList = value; }
        }

        private string _code;
        public string Code
        {
            get { return _code; }
            set { _code = value; NotifyOfPropertyChange(() => Code); }
        }

        private int _qty;
        public int Qty
        {
            get { return _qty; }
            set { _qty = value; NotifyOfPropertyChange(() => Qty); }
        }

        private int _program;
        public int Program
        {
            get { return _program; }
            set
            {
                _program = value;

                NotifyOfPropertyChange(() => Program);
            }
        }

        public OrderViewModel(IDataConnection connect)
        {
            DisplayName = "Orders";

            var allOrders = await _connect.Orders_GetByDateRange(StartDate, EndDate);
            OrderList = new BindableCollection<OrderModel>(allOrders);
            OrderListView = CollectionViewSource.GetDefaultView(OrderList);

            var allProducts = await _connect.Products_GetAll();
            ProductList = new BindableCollection<ProductModel>(allProducts);
        }
}

В основном, когда «Код» соответствует моделям, я хочу вывести связанную программу в столбец.

10.03.2021

Ответы:


1

ItemsSource, к которому привязывается DataGrid, должен содержать все свойства для привязок столбцов.

Это означает, что необходимо либо добавить свойство Program к вашему текущему OrderModel, либо создать новую модель, содержащую оба свойства.

public class OrderModel : BaseModel
{
    private DateTime _orderDate;
    public DateTime OrderDate
    {
        get { return _orderDate; }
        set { _orderDate = value; OnPropertyChanged(); }
    }

    private string _code;
    public string Code
    {
        get { return _code; }
        set { _code = value; OnPropertyChanged(); }
    }

    private int _qty;
    public int Qty
    {
        get { return _qty; }
        set { _qty = value; OnPropertyChanged(); }
    }

    private int _program;
    public int Program
    {
        get { return _program; }
        set { _program = value; OnPropertyChanged(); }
    }
}

Затем потребуется логика, чтобы связать новое значение Program со значением из другой коллекции.

Самым чистым местом для этого, скорее всего, будет изменение вашего запроса (при условии, что вы используете соединение с базой данных)

Скорее всего, это будет включать JOIN при выборе заказов.

Однако сделать это на стороне клиента, то есть после того, как данные были получены от IDataConnection, будет выглядеть так:

using System.Linq;
...

public OrderViewModel(IDataConnection connect)
{
    DisplayName = "Orders";

    var allOrders = await _connect.Orders_GetByDateRange(StartDate, EndDate);

    var allProducts = await _connect.Products_GetAll();
    ProductList = new BindableCollection<ProductModel>(allProducts);

    foreach(var order in allOrders)
    {
        //assumes "Code" is unique within `ProductList`
        order.Program = ProductList.Single(p => p.Code == order.Code);
    }
    OrderList = new BindableCollection<OrderModel>(allOrders);
    OrderListView = CollectionViewSource.GetDefaultView(OrderList);
}
10.03.2021
Новые материалы

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

стройный-i18следующий
Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

Обзор 20 основных и современных методов работы с массивами в JavaScript
Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

Да, но я чувствую необходимость указать, что это или не единственные два.
Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.