在 MVVM WPF 中将 DataTable 绑定到 DataGrid

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15775396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:26:22  来源:igfitidea点击:

Binding a DataTable to a DataGrid in MVVM WPF

c#.netwpfmvvm

提问by Ulrar

I'm quite new to the whole C# .net thing, but I searched a lot and I can't find how to make it work.

我对整个 C# .net 很陌生,但我搜索了很多,但找不到如何使其工作。

I have a DataGrid in my view, like this :

在我看来,我有一个 DataGrid,如下所示:

<DataGrid Name="SettingGrid" ItemsSource="{Binding Path=PluginSettings, Mode=OneWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="True" Margin="224.4,10,10,10"/>

PluginSettings is a DataTable, dynamically filled with different columns and row depending on what the user is doing. The PluginSettings is always up to date, I have checked that with the debug mode, the columns and row are always how I want them. But the view is never updated. After some Googling, I found that DataTable is not enumerable, so can not be binded to. I changed my binding to {Binding Path=PluginSettings.DefaultView. With that, I get the rows working perfectly, but the columns aren't.

PluginSettings 是一个数据表,根据用户的操作动态填充不同的列和行。PluginSettings 总是最新的,我已经在调试模式下检查过,列和行总是我想要的。但是视图永远不会更新。经过一番谷歌搜索,我发现 DataTable 不可枚举,因此无法绑定到。我将绑定更改为{Binding Path=PluginSettings.DefaultView. 有了这个,我让行完美地工作,但列不是。

When I add a column to my DataTable, the view never shows it. And if I understood correctly what DefaultView is, it means I can't replicate the change the user do on the Grid to the actual DataTable to save them, and that's actually my goal.

当我向 DataTable 添加一列时,视图从不显示它。如果我正确理解 DefaultView 是什么,这意味着我无法将用户在 Grid 上所做的更改复制到实际的 DataTable 以保存它们,这实际上是我的目标。

Did I miss something ? Is it just a bad choice to use DataGrid, is there something better for what I am trying to do ?

我错过了什么 ?使用 DataGrid 是不是一个糟糕的选择,有什么更好的方法适合我的尝试吗?

Hoping I made what I mean clear, English is not my first language. Thanks

希望我说清楚我的意思,英语不是我的第一语言。谢谢

回答by Federico Berasategui

  • I must mention that the use of System.Datawithin client-side code (WPF) is discouraged.
  • This includes System.Data.DataSet, System.Data.DataTable, and any other classes inside the System.Datanamespace.
  • You should create proper data models and use that instead.
  • IMO, System.Datais a server-side concept and should not be carried over to the client.
  • in WinRT, for example, it doesn't even exist. There's no System.Data, so if you ever plan to migrate your WPF application to WinRT, you'll have a lot of code to rewrite.
  • 我必须提到,System.Data不鼓励在客户端代码 (WPF) 中使用。
  • 这包括System.Data.DataSetSystem.Data.DataTableSystem.Data命名空间内的任何其他类。
  • 您应该创建适当的数据模型并使用它。
  • IMOSystem.Data是服务器端的概念,不应转移到客户端。
  • 例如,在 WinRT 中,它甚至不存在。没有System.Data,因此如果您计划将 WPF 应用程序迁移到 WinRT,您将需要重写大量代码。

Having said that, this example works in both adding new rows and adding new columns:

话虽如此,此示例适用于添加新行和添加新列:

<Window x:Class="MiscSamples.DataGridAndDataTable"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridAndDataTable" Height="300" Width="300">
    <DockPanel>
        <Button Content="Add Column" DockPanel.Dock="Top" Click="AddColumn"/>
        <Button Content="Add Row" DockPanel.Dock="Top" Click="AddRow"/>
        <DataGrid Name="SettingGrid" 
              ItemsSource="{Binding}" 
              AutoGenerateColumns="True"/>
    </DockPanel>
</Window>

Code Behind:

背后的代码:

  public partial class DataGridAndDataTable : Window
    {
        public DataTable PluginSettings { get; set; }

        public DataGridAndDataTable()
        {
            InitializeComponent();

            PluginSettings = new DataTable();

            PluginSettings.Columns.Add("Name", typeof (string));
            PluginSettings.Columns.Add("Date", typeof(DateTime));

            PluginSettings.NewRow();
            PluginSettings.NewRow();

            PluginSettings.Rows.Add("Name01", DateTime.Now);

            DataContext = PluginSettings;
        }

        private void AddColumn(object sender, RoutedEventArgs e)
        {
            PluginSettings.Columns.Add("Age", typeof (int));
            DataContext = null;
            DataContext = PluginSettings;
        }

        private void AddRow(object sender, RoutedEventArgs e)
        {
            PluginSettings.Rows.Add("Name01", DateTime.Now);
        }
    }