【问题标题】:C# WPF MVVM - Merge multiple csv to datagridC# WPF MVVM - 将多个 csv 合并到数据网格
【发布时间】:2019-06-30 03:21:24
【问题描述】:

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

  1. 有效的方法是使用 XAML 代码和代码隐藏中的绑定将文件添加到列表框。
  2. 不起作用的是合并数据以动态显示与数据网格的绑定。属性已更改,但网格未更新。

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

    }
}

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

}

dataGridview 类

    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>

当前输出:

希望的输出:

Propertychanged getting raised

【问题讨论】:

  • 我看不到您在添加文件后刷新DataGrid 内容的位置。添加按钮事件处理程序中有一个DataGridViewModel.ReturnDataTableForGridView();,但这不会更新DataGrid。没有引发 PropertyChangedCollectionChanged 事件。
  • @redcurry 我不确定如何正确解决这个问题。我看到了另一个示例,并在 datagridviewmodel 中添加了所有内容。在这里,我添加了一个数据视图,它可以通过返回数据表引发 propertychanged 事件,并将其绑定到 XAML。现在我看到它引发了事件,但网格没有更新。一些使用 = delegate {} 但没有任何反应。然后我看到数据表无法通过 propertychanged 提升,这就是我将其更改为 dataview 的原因。我还看到了 kiwipom 的这篇文章寻求帮助:LINK
  • 如果您希望数据刷新时查看 Visual Studio 中的“输出”窗口,是否看到任何绑定错误?
  • @redcurry 什么都没有。我现在已经更新了整个代码,并添加了propertychanged,因此您可以查看数据流中的具体内容。我还在这里找到了有关绑定的 ekstra 信息:来自 syned 的LINK。 XAML 更改后仍然没有。
  • @redcurry 你好。我只是得到一个答案来解决我的问题。非常感谢您的宝贵时间。 - Answar 已发布。

标签: c# wpf csv mvvm datagrid


【解决方案1】:

我的朋友帮我举了一个例子。

下面的答案:

XAML 中的 DataContext 错误。您的视图必须与您的 ViewModel 而不是您的模型进行通信。

如果您运行 MVVM,那么在视图代码隐藏中使用按钮单击事件是错误的。必须在 ViewModel 中完成。

除此之外,您的 CSV 解析器是错误的实现。只要字段包含分号、换行或使用 komma 而不是分号作为字段分隔符,它将立即中断。

阅读更多关于 CSV 文件的 RFC 规范HERE 或使用可以正确解析文件的库。前任。 ExcelDataReader 如果你想把它放到你的数据表中; ExcelDataReader.DataSet

关于功能和正确绑定的示例,请参见以下示例:

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

委托命令

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

【讨论】:

    猜你喜欢
    • 2013-04-15
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多