繁体   English   中英

将模型类的列表/集合/ IEnumerable绑定到数据网格并选择列

[英]Binding a list/collection/IEnumerable of Model Class to a Data Grid and Selecting Columns

我似乎无法通过搜索找到此答案,也无法连接到其他示例到我的方案的点。

使用MVVM模式:

  1. 如何通过视图中的ViewModel将模型类绑定到列表框/数据网格?
  2. 如何选择要显示的列?
  3. 问题2后续行动:我可以通过visual Studio UI属性进行选择吗?如果可以,如何选择?
  4. 如果使用XAML完成,我的模型/视图模型类是否可以自动完成?
  5. 使用Observable Collection,什么是正确的实现方式?
  6. 什么是“首选” XAML控件(datagrid,listbox等)

我将示例简化为:Model类:

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

视图部分:

我知道我需要为视图提供一个DataContext 许多示例显示了它是在后台代码中设置的(请参见下文),还有一些示例引用了列表框的“ StaticResource”。 我没有找到一种通过UI设置代码的方式来设置绑定的方法。

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(通过代码或UI)能否请您帮助我完成数据网格列/绑定:每个@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>

这会产生带有额外列的奇怪布局: 额外栏

这在您的窗口构造函数中是正确的:

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。 如果要每行显示一个值,或者每行显示某种漂亮的模板化UI,请使用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(“计划旧CLR对象”),没有INotifyPropertyChanged 但是,由于它已绑定在UI中,因此如果用户可以更改其上的任何属性,则需要使用INPC的正确视图模型。 如果没有,请在该DataGrid上设置IsReadOnly="True" 如果项目只是计划UI中的无效只读数据,而没有任何行为,则像您拥有的POCO很好。 只要确保UI确实是只读的即可。

MVVM并不意味着拥有模型的ViewModel。 这意味着视图模型拥有的视图模型拥有其他视图模型,这些视图模型可能深达十几层,并且该视图模型“树”反映了应用程序的基本设计。 然后,您将获得模型,这些模型是一个独立的并行层次结构,反映了数据层的必要组织。 如果要通过Web服务从数据库加载项目,则可能会有一个ProjectModel和一个ProjectViewModel。 但是某些模型没有对应的视图模型,许多视图模型没有对应的模型。

而一个小型项目可能根本不需要“模型”层。 学习时,我会毫不犹豫地暂时编写视图模型和视图。 掌握那些和模型是无关紧要的。

模型就是数据。 一个ProjectViewModel可以包装一个ProjectModel,以暴露相同的属性,但具有INPC以及其他特定于UI的属性:例如IsDirty (例如,如果它是可编辑的),或者UI绑定到ComboBoxes的查找列表(如果它具有枚举的属性)或查询类型。 它还将具有命令和方法。 除了编写包装器外,还有其他一些也许更好的方法,但是已经很晚了,可悲的是,我现在正在空白。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM