C# WPF MVVM - 将多个 csv 合并到数据网格

标签 c# wpf csv mvvm datagrid

我一直在研究这个小程序,它需要获取 CSV 文件的文件输入,将它们存储在列表框中,然后自动更新数据网格。当添加更多文件时,数据网格需要用新的文件数据扩展并添加到它旁边。

  • 有效的方法是使用 XAML 代码和代码隐藏中的绑定(bind)将文件添加到列表框。
  • 不起作用的是合并数据以动态显示与数据网格的绑定(bind)。属性发生了变化,但网格没有更新。

  • 在 DataGridViewModel 中是我的 csv 合并代码所在的位置:
    public class DataGridViewModel 
        {
       static public DataGridModel _dataGridModel = new DataGridModel();
    
        public static void ReturnDataTableForGridView()
        {
            DataTable mainTable = new DataTable();
            //-- #3 Test merge 
            foreach (var item in SidePanelViewModel.GetPathFileList())
            {
                DataTable dataTable = new DataTable();
                try
                {
    
                    string[] Lines = File.ReadAllLines(item.Filepath);
                    string[] Fields;
                    Fields = Lines[0].Split(new char[] { ';' });
                    int Cols = Fields.GetLength(0);
    
                    //1st row skal være kolonne navn; 
                    for (int X = 0; X < Cols; X++)
                        dataTable.Columns.Add(Fields[X].ToLower(), typeof(string));
    
                    DataRow Row;
                    for (int T = 1; T < Lines.GetLength(0); T++)
                    {
                        Fields = Lines[T].Split(new char[] { ';' });
                        Row = dataTable.NewRow();
                        for (int f = 0; f < Cols; f++)
                            Row[f] = Fields[f];
                        dataTable.Rows.Add(Row);
                    }
                    //-- Merges every files(tables) into one.
                    mainTable.Merge(dataTable);                   
                }
                catch (Exception)
                {
                    return null;
                }
            }
            //-- Sets the datatablemerger which raises the propertychanged 
            _dataGridModel.DatatableMerger = mainTable;
    
        }
    }
    

    数据网格模型类
       public class DataGridModel : INotifyPropertyChanged
    {
    
    
        DataTable _dataTableMerger { get; set; } = new DataTable();
    
        public DataTable DatatableMerger
        {
            get
            {
                return _dataTableMerger;
            }
            set
            {
                _dataTableMerger = value;
                OnPropertychanged("DatatableMerger");
            }
        } 
    
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertychanged([CallerMemberName] string caller = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
        }
    
    }
    

    数据 GridView 类
        public DataGridView()
        {
            InitializeComponent();
        }
    

    XAML 代码:
            <DataGrid x:Name="MainDataGrid"  Grid.Row="1" VerticalAlignment="Stretch" Height="auto" ItemsSource="{Binding Path=DatatableMerger, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" >
        </DataGrid>
    </Grid>
    <UserControl.DataContext>
         <Model:DataGridModel/>
    </UserControl.DataContext>
    

    当前输出:

    Currently output - Picture

    期望输出:

    Wished output - picture

    Propertychanged getting raised

    最佳答案

    我的 friend 帮我举了一个例子。
    继安斯瓦尔之后:
    XAML 中的 DataContext 是错误的。您的 View 必须与您的 ViewModel 而不是您的模型进行通信。
    如果您运行 MVVM,那么在 Views 代码隐藏中使用按钮单击事件是错误的。它必须在 ViewModel 中完成。
    除此之外,您的 CSV 解析器是错误的实现。只要字段包含分号、新行或 komma 用作字段分隔符而不是分号,它将立即中断。
    阅读更多关于 CSV 文件的 RFC 规范 HERE或使用可以正确解析文件的库。前任。 ExcelDataReader如果你想把它放到你的数据表中; ExcelDataReader.DataSet
    关于功能和正确绑定(bind)的示例,请遵循以下示例:
    主窗口.cs

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
    
    XAML
        <Window.DataContext>
        <local:DataGridViewModel/>
    </Window.DataContext>
    <Grid>
        <DataGrid Margin="0,0,0,35" ItemsSource="{Binding DatatableMerger}"/>
        <Button Content="Add rows" Margin="0,0,10,10" Command="{Binding AddRowsButtonClickCommand}" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75"/>
    </Grid>
    
    DataGridModel.cs
        public class DataGridModel
    {
        public DataTable DatatableMerger { get; set; }
    }
    
    DataGridViewModel.cs
        public class DataGridViewModel : INotifyPropertyChanged
    {
        private readonly DataGridModel _dataGridModel = new DataGridModel();
    
        public DataTable DatatableMerger => _dataGridModel.DatatableMerger;
    
        public ICommand AddRowsButtonClickCommand => new DelegateCommand(o => ReturnDataTableForGridView());
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
        public void ReturnDataTableForGridView()
        {
            var dt = new DataTable();
    
            dt.Columns.Add("Foo");
            dt.Columns.Add("Bar");
            dt.Columns.Add("Baz");
    
            for (var i = 0; i < 5; i++)
                dt.Rows.Add($"Value {i}", i, DateTime.Now.AddSeconds(i));
    
            _dataGridModel.DatatableMerger = dt;
            OnPropertyChanged(nameof(DatatableMerger));
        }
    }
    
    委托(delegate)人命令
        public class DelegateCommand : ICommand
    {
        private readonly Predicate<object> _canExecute;
        private readonly Action<object> _execute;
    
        public event EventHandler CanExecuteChanged;
    
        public DelegateCommand(Action<object> execute) : this(execute, null) { }
    
        public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }
    
        public bool CanExecute(object parameter)
        {
            if (_canExecute is null)
                return true;
    
            return _canExecute(parameter);
        }
    
        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    
        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
    
    对于合并功能。使用 YourMainTableName = Mergetables(Table1, table2); 调用函数
            public DataTable MergeTables(DataTable Table1, DataTable Table2)
        {
            DataTable Mergetable = new DataTable();
    
            foreach (DataColumn d in Table1.Columns)
            {
                Mergetable.Columns.Add(d.ColumnName);
            }
    
            foreach (DataColumn d in Table2.Columns)
            {
                Mergetable.Columns.Add(d.ColumnName);
            }
    
            int Table1Cols = Table1.Columns.Count;
            int Table1Rows = Table1.Rows.Count;
            int Table2Cols = Table2.Columns.Count;
            int Table2Rows = Table2.Rows.Count;
    
            DataRow row2;
            bool end = false;
            int RowCount = 0;
    
            while (!end)
            {
                end = true;
                if (RowCount < Table1Rows || RowCount < Table2Rows)
                {
                    end = false;
                    row2 = Mergetable.NewRow();
    
                    if (RowCount < Table1Rows)
                    {
                        for (int col = 0; col < Table1Cols; col++)
                        {
                            row2[col] = Table1.Rows[RowCount][col];
                        }
                    }
    
                    if (RowCount < Table2Rows)
                    {
                        for (int col = 0; col < Table2Cols; col++)
                        {
                            row2[col + Table1Cols] = Table2.Rows[RowCount][col];
                        }
                    }
                    Mergetable.Rows.Add(row2);
                }
                RowCount++;
            }
            return Mergetable;
        }
    

    关于C# WPF MVVM - 将多个 csv 合并到数据网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54549113/

    相关文章:

    wpf - 在 WPF 中的 MVVM 中的 Viewmodel 之间传递值

    azure - 使用电子邮件字段在 Azure AD 中批量创建用户

    linux - CSV 到 XLS linux 脚本

    c# - 来自 MS-Access 与 .NET 的相同查询的排序顺序不同

    c# - 如何在 Visual Studio 中连接到 Sqlite 并创建数据库?

    c# - 如何在 ComboBox 的开头和结尾显示 ComboBoxItem

    c# - WindowClosing方法发生异常时WPF应用程序关闭

    c# - 表单从左到右调整大小的动画

    C# 通用和特定扩展方法组合歧义

    PHP curl 获取 header 不适用于超过 300 个条目的 cron 作业