List<T> 与 BindingList<T> 的子项在附加到 UltraWinGrid 时表现不同

Child of List<T> vs. BindingList<T> Behaving Differently When Attached to UltraWinGrid

我正在尝试创建我的数据模型的内存表示。它是具有“序列”和“操作”的“有效负载”。一个序列可以在它下面有其他序列,并且每个序列都有与该序列关联的操作列表。

这是我用来测试的一些模拟数据,以提供一个想法:

public static void CreateMockData() //for making a car
{
    //parameters: SequenceNo (int), ParentSequenceNo (int?), SequenceType (enum), Description (string)
    Repository.SequencesList.Add(new Sequence(0, null, SequenceType.Standard, "Car assembly"));
    //parameters: ParentSequenceNo (int), OperationNo (int), Activity (string)
    Repository.OperationsList.Add(new Operation(0, 100, "Gather body parts"));
    Repository.OperationsList.Add(new Operation(0, 200, "Gather rims and tires"));

    Repository.SequencesList.Add(new Sequence(1, 0, SequenceType.Alternate, "Wheel assembly"));
    Repository.OperationsList.Add(new Operation(0, 300, "Mount tires on rims"));
    Repository.OperationsList.Add(new Operation(0, 400, "Inflate tires"));

    Repository.SequencesList.Add(new Sequence(2, 0, SequenceType.Alternate, "Body assembly"));
    Repository.OperationsList.Add(new Operation(2, 500, "Paint car body parts"));
    Repository.OperationsList.Add(new Operation(0, 600, "Bolt body parts to car body"));

    Repository.OperationsList.Add(new Operation(0, 700, "Install engine"));
        
    Repository.SequencesList.Add(new Sequence(3, 2, SequenceType.Parallel, "Battery charging and installation"));
    Repository.OperationsList.Add(new Operation(3, 800, "Charge battery"));
    Repository.OperationsList.Add(new Operation(3, 900, "Install battery"));

    Repository.OperationsList.Add(new Operation(0, 1000, "Bolt wheels to car"));
        
    Repository.OperationsList.Add(new Operation(0, 1100, "Do final inspection"));
    Repository.OperationsList.Add(new Operation(0, 1200, "Sign off inspection"));
}

“存储库”class 充当模拟数据库,保存所有可能的序列和操作:

public static class Repository //mock db
{
    public static List<Sequence> SequencesList = new List<Sequence>(); //dumb list because it's a mock db, no need for binding stuff
    public static List<Operation> OperationsList = new List<Operation>(); //dumb list because it's a mock db, no need for binding stuff
}

这是“序列”和“操作”classes

public enum SequenceType { Standard = 0, Alternate = 1, Parallel = 2 }

public class Sequence
{
    public Sequence() { }

    public Sequence(int SequenceNo, int? ParentSequenceNo, SequenceType Type, string Description)
    {
        this.SequenceNo = SequenceNo;
        this.ParentSequenceNo = ParentSequenceNo;
        this.Type = Type;
        this.Description = Description;
    }

    private Guid internalID = Guid.NewGuid();
    public Guid ID { get { return internalID; } }
    public int SequenceNo { get; set; }
    public int? ParentSequenceNo { get; set; } //if this is the main sequence then null, all others have a parent
    public SequenceType Type { get; set; }
    public string Description { get; set; }
    public int? BranchOperation { get; set; }
    public int? ReturnOperation { get; set; }

    //children
    //part of the problem here
    //if i change either of these list types to BindingList<T> they keep getting called over and over after binding to the grid...

    //public BindingList<Sequence> SubSequences { get { return Repository.SequencesList.FindAll(x => x.ParentSequenceNo == this.SequenceNo).ToBindingList(); }}
    //above will get called over and over...
    public List<Sequence> SubSequences { get { return Repository.SequencesList.FindAll(x => x.ParentSequenceNo == this.SequenceNo); } } 
    public List<Operation> Operations { get { return Repository.OperationsList.FindAll(x => x.ParentSequenceNo == this.SequenceNo); } }

    public void Save()
    {
        Repository.SequencesList[Repository.SequencesList.FindIndex(x => x.ID == this.ID)] = this;
    }

    public void Delete()
    {
        Repository.SequencesList[Repository.SequencesList.FindIndex(x => x.ID == this.ID)].Delete();
    }
}

public class Operation
{
    public Operation() { }

    public Operation(int ParentSequenceNo, int OperationNumber, string Activity) 
    {
        this.ParentSequenceNo = ParentSequenceNo;
        this.Activity = Activity;
    }

    private Guid internalID = Guid.NewGuid();
    public Guid ID { get { return internalID; } }
    public int ParentSequenceNo { get; set; }
    public int OperationNumber { get; set; }
    public string Activity { get; set; }
    public string OperationText { get; set; }
    public double LaborHours { get; set; } = 0;

    public void Save()
    {
        Repository.OperationsList[Repository.OperationsList.FindIndex(x => x.ID == this.ID)] = this;
    }

    public void Delete()
    {
        Repository.OperationsList[Repository.OperationsList.FindIndex(x => x.ID == this.ID)].Delete();
    }
}

问题...

我正在使用 Infragistics UltraWinGrid 控件。

  1. 当我将 List<T> 数据类型用于 Sequence 子列表时,事情按我预期的方式工作,但是,子带(这是两种不同的类型,List<Sequence>List<Operation>),仅显示序列列。见图..
  2. 当我为子列表使用 BindingList<T> 类型时,它们的子绑定列表不断被调用,只是耗尽了内存,程序永远不会启动。 List<T> 类型不会发生这种情况。

将列表绑定到网格:

private void FrmMain_Load(object sender, EventArgs e)
{
    MockDataFiller.CreateMockData();
    List<Sequence> zeroSequenceList = new List<Sequence>();
    zeroSequenceList.Add(Repository.SequencesList.FirstOrDefault(x => x.SequenceNo == 0));
    gridSequences.DataSource = zeroSequenceList;
}

带列表的绑定网格示例(针对问题 #1):

我的最终目标是让它与 BindingList 一起工作(问题 2),但是,我真的迷路了。非常感谢任何帮助我指出正确方向的帮助。谢谢。

Gets or sets the max band depth. Grid will load upto MaxBandDepth number of bands. Note that you have to set the MaxBandDepth before binding the UltraGrid.

来自 Infragistics 文档:

使用此 属性 强制网格仅加载特定数量的波段。这可以在你有 递归数据关系 的情况下使用,其中 table 与其自身相关并且你只希望网格仅向下钻取带层次结构到特定级别。

此 属性 的默认值为 100,范围为 1-100(含)。如果设置为小于 1 或大于 100 的值,则抛出 ArgumentOutOfRange 异常。

注意:您必须在将 UltraGrid 绑定到数据源之前设置 MaxBandDepth 才能使此 属性 生效。

MaxBandDepth Property