简体   繁体   English

在DataGridView中显示用户对象的IList

[英]Displaying an IList of User Objects in a DataGridView

We are Java developers trying to support a project in C# and can't seem to figure out how to bind a list of objects which is constantly being updated in and by the UI to a DataGridView so they are visible as soon as they are added. 我们是Java开发人员,他们试图用C#支持一个项目,但是似乎无法弄清楚如何将一个对象列表(该对象在UI中以及由UI不断更新)绑定到DataGridView,因此一旦添加它们就可以看到它们。

There is a requirement that the UI track its use and display it back to the user in a data grid (for human factors analysis). UI要求跟踪其使用并在数据网格中将其显示回给用户(用于人为因素分析)。 We are implementing the IList interface and subclassing one of our logging classes: 我们正在实现IList接口,并继承我们的日志记录类之一:

public class DataSourceAppender : Logger, IList<LogEvent>
{
    private List<LogEvent> _events = new List<LogEvent>();

We add (append) a new LogEvent object to the list each time the user clicks a control or performs some operation of interest, recording various details of the interaction in the order in when they occurred. 每次用户单击控件或执行某些感兴趣的操作时,我们都会在列表中添加(附加)新的LogEvent对象,并按发生时的顺序记录交互的各种详细信息。 This list is dumped to a file at the end of the user test session for analysis. 此列表在用户测试会话结束时转储到文件中以进行分析。 Now we need to show this to the user in a data grid as the session is progressing. 现在,我们需要在会话进行过程中在数据网格中向用户显示此信息。

Our main method contains: 我们的主要方法包括:

// create a new logger(appender) which holds all our log events
consoleSource = new DataSourceAppender();
consoleSource.Append("INIT", "Client Initialized");

// add the logger the the console data grid and wire-up the data binding
mainform.consoleDataGrid.AutoGenerateColumns = true;
mainform.consoleBinding.DataSource = typeof(LogEvent);
mainform.consoleBinding.DataSource = consoleSource;
consoleSource.Binding = mainform.consoleBinding;

The append method in the DataSourceAppender (aka consoleSource) contains: DataSourceAppender(又名consoleSource)中的append方法包含:

public override void Append(string category, object entry)
{
    long now = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;

    if (lastevent == 0) lastevent = now;

    try
    {
        LogEvent logevent = new LogEvent(now, category, (now - lastevent), Log.Interval, entry);

        // add the new log event to this data sorce
        lock (_events)
        {
            _events.Add(logevent);
        }
        if (_binding != null) _binding.ResetBindings(false);
    }
    catch (Exception e)
    {
        System.Console.Error.WriteLine(this.GetType().FullName + " error: " + e + ":" + e.Message);
    }
}

The results are the first "INIT" entry is displayed in the data grid but none of the other events in the DataSourceAppender (aka consoleSource) are displayed. 结果是第一个“ INIT”条目显示在数据网格中,但DataSourceAppender(aka consoleSource)中没有其他事件显示。 They are all written to disk later so we know the Append method is getting called and otherwise working fine. 它们都在以后写入磁盘,因此我们知道Append方法正在被调用,否则可以正常工作。

A few goals: 一些目标:

  • We are trying to stick to the Designer and not mess with generated code. 我们正在努力坚持设计器,不要将生成的代码弄乱。
  • We would like to wire up the binding in the Main() method. 我们想在Main()方法中绑定绑定。
  • We would like the public properties of the LogEvent class to appear as column headings 我们希望LogEvent类的公共属性显示为列标题
  • This must remain a single-threaded application 这必须保持为单线程应用程序

We have been scouring forums and the MSDN pages and find loads of examples for binding to databases and manually updating the data grid, but precious little information on programmatically adding data to the data grid through its backing data store. 我们一直在搜索论坛和MSDN页面,并找到大量示例以绑定到数据库并手动更新数据网格,但是关于通过编程将数据通过其后备数据存储添加到数据网格的信息很少。

Any help would be greatly appreciated. 任何帮助将不胜感激。

Since we can't see your entire DataSourceAppender class, I can't tell for sure what you're trying to do. 由于看不到整个DataSourceAppender类,因此无法确定您要做什么。

I see you've assigned consoleSource as your datasource, so the fact that you're not seeing any newly added items in the grid tells me you haven't correctly implemented IList to wrap _events ; 我看到您已将consoleSource分配为您的数据源,因此您没有在网格中看到任何新添加的项目这一事实表明,您没有正确实现IList来包装_events

But you're making life harder than necessary by trying to implement IList anyway. 但是无论如何,通过尝试实现IList都会使生活变得不必要的艰辛。 Just assign _events as your datasource. 只需将_events分配为您的数据源。 If you like, you can expose it as a property of DataSourceAppender : 如果愿意,可以将其公开为DataSourceAppender的属性:

public IEnumerable<LogEvent> EventList { get { return _events; } }

then: 然后:

mainform.consoleBinding.DataSource = consoleSource.EventList;

Also you don't need this line: 另外,您不需要此行:

mainform.consoleBinding.DataSource = typeof(LogEvent);

Basically this is all there is to it: 基本上,这就是全部:

events = new Collection<LogEvent>(); // or List<> if you want
bindingSource.DataSource = events;
dataGridView.DataSource = bindingSource;

then add items like: 然后添加以下内容:

events.Add(event);
bindingSource.ResetBindings(false);

or simply : 或者简单地:

bindingSource.Add(event);

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

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