using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls;
using Telerik.WinControls.UI;

namespace TestGridViewScroll
{
    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        BindingList<TestData> mainData_;

        List<TestData> backupData_;
        private Dictionary<Guid, bool> expandedStates = new Dictionary<Guid, bool>();

        public RadForm1()
        {
            InitializeComponent();

            backupData_ = new List<TestData>();
            for (int i = 0; i < 3; ++i)
            {
                var testData = new TestData(i);

                for (int j = 0; j < 30; ++j)
                {
                    testData.Childs.Add(new ChildData(j.ToString()));
                }

                backupData_.Add(testData);
            }

            mainData_ = new BindingList<TestData>();
            radGridViewMain.DataSource = mainData_;
        }

        private void radButton1_Click(object sender, EventArgs e)
        {
            int sValue = radGridViewMain.TableElement.VScrollBar.Value;

            foreach (var row in radGridViewMain.Rows)
            {
                if (row.DataBoundItem != null
                    && row.DataBoundItem is TestData data)
                {
                    Guid groupGuid = (Guid)data.DataUniqueID;

                    if (expandedStates.ContainsKey(groupGuid))
                    {
                        expandedStates[groupGuid] = row.IsExpanded;
                    }
                    else
                    {
                        expandedStates.Add(groupGuid, row.IsExpanded);
                    }
                }
            }

            radGridViewMain.BeginUpdate();

            try
            {
                mainData_.Clear();
                foreach (var data in backupData_)
                {
                    mainData_.Add(data);
                }

                foreach (var row in radGridViewMain.Rows)
                {
                    if (row.DataBoundItem != null
                        && row.DataBoundItem is TestData data)
                    {
                        Guid groupGuid = data.DataUniqueID;
                        if (expandedStates.ContainsKey(groupGuid))
                        {
                            row.IsExpanded = expandedStates[groupGuid];
                        }
                        else
                        {
                            expandedStates.Add(groupGuid, row.IsExpanded);
                        }
                    }
                }
            }
            finally
            {
                radGridViewMain.EndUpdate();
            }
            
            if (sValue < radGridViewMain.TableElement.VScrollBar.Maximum)
            {
                radGridViewMain.TableElement.VScrollBar.Value = sValue;
            }
        }

        private void RadForm1_Load(object sender, EventArgs e)
        {
            GridViewTemplate template = new GridViewTemplate
            {
                AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill,
                EnableSorting = false,
                AutoGenerateColumns = false,
                AllowAddNewRow = false,
                SelectLastAddedRow = false,
                AllowRowResize = false
            };
            template.AllowEditRow = true;
            template.AllowAddNewRow = false;
            radGridViewMain.MasterTemplate.Templates.Add(template);

            template.Columns.Add(new GridViewTextBoxColumn("Child Name") { FieldName = "ChildName" });

            GridViewRelation relation = new GridViewRelation(radGridViewMain.MasterTemplate)
            {
                ChildTemplate = template
            };
            relation.ChildColumnNames.Add("Childs");
            radGridViewMain.Relations.Add(relation);
        }
    }

    public class TestData
    {
        public TestData(int i)
        {
            name = i.ToString();
            option1 = ++i;
            option2 = ++i;
            option3 = ++i;

            dataId = Guid.NewGuid();

            childs = new List<ChildData>();
        }

        private string name;
        private int option1;
        private int option2;
        private int option3;
        private Guid dataId;
        private List<ChildData> childs;

        public List<ChildData> Childs
        {
            get { return childs; }
            set { childs = value; }
        }

        public Guid DataUniqueID { get { return dataId; } }
        public string Name { get { return name; } set { name = value; } }
        public int Option1 { get { return option1; } set { option1 = value; } }
        public int Option2 { get { return option2; } set { option2 = value; } }
        public int Option3 { get { return option3; } set { option3 = value; } }
    }

    public class ChildData
    {
        string childName;

        public ChildData(string inputData)
        {
            childName = inputData;
        }

        public string ChildName { get { return childName;  } set { childName = value; } }
    }
}
