Привязка списка / коллекции / IEnumerable класса модели к сетке данных и выбор столбцов - PullRequest
0 голосов
/ 21 мая 2019

Я не могу найти этот ответ с помощью поиска и не могу подключиться к точкам из других примеров в моем сценарии.

Использование шаблона MVVM:

  1. Как связать мой класс модели через ViewModel в моем представлении со списком / сеткой данных?
  2. Как мне выбрать столбцы, которые нужно отобразить?
  3. Вопрос 2: Продолжение. Могу ли я выбирать в свойствах визуального интерфейса Studio, если да, то как?
  4. Если сделано с XAML, есть ли автозаполнение с моим классом model / viewmodel?
  5. Как правильно реализовать Observable Collection?
  6. Что такое «предпочтительный» элемент управления XAML (сетка данных ?, список? И т. Д.)

Я упростил мой пример до следующего: Класс модели:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;


namespace TestListBinding.Models
{
    public class ProjectModel
    {
        public string Id { get; set; }
        public string ProjectTitle { get; set; }
        public string ProjectDetails { get; set; }
    }
}

Класс ViewModel:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using TestListBinding.Models;

namespace TestListBinding.ViewModels
{
    public class ProjectViewModel
    {
        private ProjectModel _project;
        private ObservableCollection<ProjectModel> _projects;

        public ProjectViewModel()
        {
            _projects = new ObservableCollection<ProjectModel>();
            var proj = new ProjectModel();
            for (int i = 1; i <= 3; i++)
            {
                proj.Id = "ID" + i.ToString();
                proj.ProjectTitle = "Project " + i.ToString();
                proj.ProjectDetails = "Details about this: " + i.ToString();
                _projects.Add(proj);
                proj = new ProjectModel();
            }
        }

        public IEnumerable<ProjectModel> Projects
        {
            get { return _projects; }
        }
    }
}

The View Part:

Я знаю, что мне нужно иметь DataContext для просмотра. Многие примеры показывают, что он установлен в коде (см. Ниже), а некоторые примеры ссылаются на «StaticResource» для списка. Я не нашел способа настроить привязки через пользовательский интерфейс в соответствии с настройками моего кода.

MainWindow.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TestListBinding.ViewModels;

namespace TestListBinding
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ProjectViewModel();//is this correct, or is there an alternative method via XAML/control properties?
        }
    }
}

XAML (через код или пользовательский интерфейс) Можете ли вы помочь мне заполнить столбцы / привязки таблицы данных: Обновлено за @ EdPlunkett

    <Window x:Class="TestListBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestListBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid HorizontalAlignment="Left" Height="239" Margin="42,32,0,0" VerticalAlignment="Top" Width="435" ItemsSource="{Binding Projects}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Project Title" Binding="{Binding ProjectTitle}"/>
                <DataGridTextColumn Header="Project Details" Binding="{Binding ProjectDetails}"/>
            </DataGrid.Columns>

        </DataGrid>

    </Grid>
</Window>

Это дает странный макет с дополнительными столбцами: Extra Columns

1 Ответ

1 голос
/ 21 мая 2019

Это правильно в вашем конструкторе окон:

DataContext = new ProjectViewModel();

И это должно показать вам некоторые вещи в сетке:

<DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Id}" Header="ID"  />
    <DataGridTextColumn Binding="{Binding ProjectTitle}" Header="Project Title" />
    <DataGridTextColumn Binding="{Binding ProjectDetails}" Header="Project Details" />
</DataGrid.Columns>

Пользователи WPF обычно не используют материалы панели дизайнера / свойств. Это не здорово и не улучшилось за десять лет. Вам не повезло с автозаполнением и в этом случае.

Предпочитаемый контроль? Зависит от того, что вы хотите: если вам нужно несколько столбцов в строке, используйте DataGrid или ListView. Если вы хотите, чтобы одно значение отображалось в строке, или какой-то симпатичный шаблонный интерфейс в строке, используйте ListBox.

Быстрый список:

<ListBox
    ItemsSource=“{Binding Projects}”
    DisplayMemberPath=“ProjectTitle”
    />

DisplayMemberPath не привязан. Это строка, которая задает имя свойства того, что вы отображаете в ListBox.

<Ч />

Я бы лично сделал это следующее изменение, хотя оно совершенно необязательно. То, что у вас есть, будет отлично работать: DataGrid.ItemsSource не возражает против привязки к свойству, объявленному как IEnumerable<T>. Объявленный тип DataGrid.ItemsSource не является универсальным System.Collections.IEnumerable. Но более обычно и часто удобно выставлять наблюдаемую коллекцию, подобную этой.

public ObservableCollection<ProjectModel> Projects
{
    get { return _projects; }
}

Когда вы говорите «класс модели», я могу ошибаться, но мне интересно, есть ли здесь терминологическая вещь: ваш ProjectModel - это класс модели, потому что он в основном POCO («Plan Old CLR Object»), без INotifyPropertyChanged. Но поскольку он связан в пользовательском интерфейсе, если пользователь может изменить какие-либо свойства, вам понадобится правильная модель представления с INPC. А если нет, установите IsReadOnly="True" для этой DataGrid. Если проекты просто планируют мертвые данные только для чтения в пользовательском интерфейсе без какого-либо поведения, то POCO, как у вас, - это хорошо. Просто убедитесь, что пользовательский интерфейс действительно только для чтения.

MVVM не означает модель представления, которая владеет моделями. Это означает, что viewmodel владеет viewmodels, которые владеют другими viewmodels, может быть, с дюжиной слоев в глубине, и это «дерево» viewmodel отражает дерево проекта. Затем у вас есть модели, представляющие собой отдельную параллельную иерархию, отражающую необходимую организацию уровня данных. Если вы загружаете проекты из БД через веб-сервис, вы, вероятно, имеете ProjectModel и ProjectViewModel. Но некоторые модели не имеют аналогов модели, а многие модели не имеют аналогов модели.

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

Модель - это просто данные. ProjectViewModel может обернуть ProjectModel, предоставляя идентичные свойства, но с INPC, а также другие свойства, относящиеся к пользовательскому интерфейсу: IsDirty, например, если он редактируемый, или списки поиска для пользовательского интерфейса для привязки к ComboBox, если он имеет свойства, которые являются тип перечисления или поиска. Он также будет иметь команды и методы. Есть и другие, возможно, более подходящие подходы, чем написание обертки, но уже поздно, и я, к сожалению, в данный момент рисую пробел.

...