0
votes

I have a model that has a list of models inside of it (simplified):

public class GridItemModel {
    public int ID { get; set; }
    public string Name { get; set; }
    public List<GridItemInventoryModel> Inventory { get; set; }
}

public class GridItemInventoryModel {
    public int Quantity { get; set; }
}

I bind my data to the grid view like so (gridItems is a list of GridItemModel):

gridItems = dal.GetInventoryGrid().ToList();

gridInventory.DataSource = gridItems;

gridInventory is the DevXpress GridControl.

I've implemented these methods from the gridview:

    private void gridView1_MasterRowGetChildList(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetChildListEventArgs e) {
        GridItemModel i = (GridItemModel)gridView1.GetRow(e.RowHandle);
        e.ChildList = new BindingSource(i, "Inventory");
    }

    private void gridView1_MasterRowGetRelationName(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetRelationNameEventArgs e) {
        e.RelationName = "Inventory";
    }

    private void gridView1_MasterRowGetRelationCount(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetRelationCountEventArgs e) {
        e.RelationCount = 1;
    }

    private void gridView1_MasterRowEmpty(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowEmptyEventArgs e) {
        GridItemModel i = (GridItemModel)gridView1.GetRow(e.RowHandle);
        e.IsEmpty = i == null;
    }

Which then makes my grid look like so:

enter image description here

When using various filters some of the items in the child view are hidden, and I need the Quantity on the end column to reflect the sum of only the visible child records.

I've so far overridden gridView1_CustomUnboundColumnData as explained here: http://www.wenda.io/questions/5156824/how-to-make-the-sum-of-each-detail-gridview-and-populated-in-the-footer-of-maste.html But I don't have DataRows they can only be cast to GridItemModel.

And I have access to my items within the grid:

GridView view = sender as GridView;
if (e.Column.FieldName != "colCalcQty") return;
if (!e.IsGetData) return;
var list = (view.DataSource as IList);

var item = (list[e.ListSourceRowIndex] as GridItemModel);

But item.Inventory always shows all the inventory models instead of those that the filter hasn't removed.

I have access to both the Parent and Child grids via gridView1 and gridView2 respectively.

How am I able to create a summed column from the visible child views quantity field with the setup I have?

Edit: I filter my view a couple of different ways, firstly I have ShowAutoFilterRow enabled on my grid but this only filters the parent records.

Then I have a combobox elsewhere on my form which on the selected index changed event calls this code:

        InventoryLibrary.DataTransferObjects.SimpleLocationModel location = ((ComboBoxEdit)cbeLocationsFilter).SelectedItem as InventoryLibrary.DataTransferObjects.SimpleLocationModel;
        InventoryLibrary.DataTransferObjects.SimpleLocationModel subLocation = ((ComboBoxEdit)cbeSubLocationsFilter).SelectedItem as InventoryLibrary.DataTransferObjects.SimpleLocationModel;

        string itemFilterString = "";
        string locationFilterString = "";


        if (location != null) {
            itemFilterString += String.Format("[LocationNames] LIKE '%{0}%'", location.Name);
            locationFilterString += String.Format("[LocationAndSublocation] LIKE '%{0}%'", location.Name);
        }

        if (subLocation != null) {

            if (location != null) itemFilterString += " AND ";
            itemFilterString += String.Format("[LocationNames] LIKE '%{0}%'", subLocation.Name);

            if (location != null) locationFilterString += " AND ";
            locationFilterString += String.Format("[LocationAndSublocation] LIKE '%{0}%'", subLocation.Name);
        }

        gridView1.ActiveFilterString = itemFilterString;
        gridView2.ActiveFilterString = locationFilterString;

This is what filters down the detail views when gridView2.ActiveFilterString has a filter string applied.

1

1 Answers

2
votes

You need to get DetailView for current row and sum quantity of all DetailView's filtered rows. To get DetailView you can use GridView.GetDetailView method and to get filtered rows you can use undocumented GridView.DataController.GetAllFilteredAndSortedRows method. If DetailView is null then you need to get «DevExpress filter engine» and use it with your GridItemModel.Inventory list. You can get this engine from DevExpress controls such:

  • GridControl
  • PivotGridControl
  • FilterControl
  • e.t.c.

Here is example for gridView1_CustomUnboundColumnData event and GridControl as «DevExpress filter engine». For this example you need to add additional GridControl0 and add a GridView1 to this control.

if (!e.IsGetData || e.Column.FieldName != "colCalcQty")
    return;

var rowHandle = gridView1.GetRowHandle(e.ListSourceRowIndex);
var view = gridView1.GetDetailView(rowHandle, 0);

int quantity = 0;

if (view == null)
{
    var gridItem = (GridItemModel)e.Row;

    gridControl2.DataSource = gridItem.Inventory;
    gridControl2.RefreshDataSource();
    gridView3.ActiveFilterString = gridView2.ActiveFilterString;

    view = gridView3;
}

foreach (var row in view.DataController.GetAllFilteredAndSortedRows())
{
    var gridItemInventory = (GridItemInventoryModel)row;
    quantity += gridItemInventory.Quantity;
}

e.Value = quantity;

Also you need to refresh your MainView after setting a filter to DetailView:

gridView2.ActiveFilterString = "Some filter criteria";
gridView1.RefreshData();


0 - gridControl2 in example.
1 - gridView3 in example.