简体   繁体   English

C#WPF MVVM-将多个csv合并到datagrid

[英]C# WPF MVVM - Merge multiple csv to datagrid

I've been working on this little program, that needs to take file inputs of CSV files, store them in a listbox, and then update automatically the datagrid. 我一直在研究这个小程序,它需要获取CSV文件的文件输入,将它们存储在列表框中,然后自动更新datagrid。 When there is added more files, the datagrid needs to expand with the new file data and add next to it. 当添加更多文件时,datagrid需要使用新文件数据进行扩展并在其旁边添加。

  1. What works is adding files to the listbox with the binding in the XAML code and codebehind. 有效的方法是将文件添加到具有XAML代码和代码隐藏中的绑定的列表框中。
  2. What doesn't work is merging the data to display dynamically with the binding to the datagrid. 无效的是将数据合并到与数据网格的绑定以动态显示。 Property changed are raised, but grid aren't updating. 已更改属性,但网格未更新。

In DataGridViewModel is where my csv merge code is: 在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;

    }
}

The DataGridModel class DataGridModel类

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

}

The dataGridview class dataGridview类

    public DataGridView()
    {
        InitializeComponent();
    }

The XAML code: 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: 当前输出:

当前输出-图片

Wished output: 希望的输出:

希望输出-图片

Propertychanged getting raised 物业变更筹集资金

My friend of mine helped me out with an example. 我的朋友以一个例子帮助了我。

Following ansvar: 跟随ansvar:

Your DataContext in the XAML is wrong. XAML中的DataContext错误。 Your view must cummunicate with your ViewModel and not your Model. 您的视图必须与ViewModel而不是Model保持一致。

If you run MVVM, then it's wrong to use button click events in your Views codebehind. 如果运行MVVM,则在后面的“视图”代码中使用按钮单击事件是错误的。 It must be done in the ViewModel. 它必须在ViewModel中完成。

Besides this, your CSV parser is wrong implementet. 除此之外,您的CSV解析器是错误的工具。 It will break as soon as a field contains semikolon, new lines, or if komma is used as a fieldseparator instead of semikolon. 一旦字段包含分号,换行符,或者如果将komma用作字段分隔符而不是分号,则它将中断。

Read more about etc. RFC specifikation about CSV files HERE or use a libary that can parse the files correctly. 阅读更多有关等的内容。有关CSV文件的RFC规范,请在这里使用或使用可以正确解析文件的库。 ex. 例如 ExcelDataReader ANd if you want it into your DataTable; ExcelDataReader ANd,如果您希望将其放入数据表; ExcelDataReader.DataSet ExcelDataReader.DataSet

Regarding an example of functional and correct binding follow below examble: 关于功能和正确绑定的示例,请参见以下说明:

MainWindow.cs MainWindow.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

The XAML 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>

The DataGridModel.cs DataGridModel.cs

    public class DataGridModel
{
    public DataTable DatatableMerger { get; set; }
}

The DataGridViewModel.cs 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));
    }
}

The delegate commands 委托命令

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

And for the merge funktion. 并为合并功能。 Call the function with YourMainTableName = Mergetables(Table1, table2); 使用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;
    }

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

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