What are the effective ways to persist the state of expanded/collapsed row when we re-bind the datasource?
There is no built in support for this, but you could track the expand states and save them to disk and reload them. Here is a little sample that does this using an XML file to save the primary keys for the expanded rows. (It assumes only a parent-child grid. For multi-levels, it would be more complicated.)
C#
ArrayList expandState = new ArrayList();
private void gridDataBoundGrid1_RowExpanded(object sender, GridRowEventArgs e)
{
//assumes a primary key value in "parentID" column
int col = this.gridDataBoundGrid1.Binder.NameToColIndex(keyColumn);
int key = (int) this.gridDataBoundGrid1[e.RowIndex, col].CellValue;
expandState.Add(key);
}
private void gridDataBoundGrid1_RowCollapsed(object sender, GridRowEventArgs e)
{
//assumes a primary key value in keyColumn column
int key = (int) this.gridDataBoundGrid1[e.RowIndex, this.gridDataBoundGrid1.Binder.NameToColIndex
(keyColumn)].CellValue;
expandState.Remove(key);
}
private void Form1_Closing(object sender, CancelEventArgs e)
{
SaveState();
}
private void LoadState()
{
string fileName = "persistedExpandStates.xml";
if(File.Exists(fileName))
{
expandState.Clear();
Stream s = File.OpenRead(fileName);
try
{
XmlSerializer serializer = new XmlSerializer(typeof(int[]));
expandState = new ArrayList((int[])serializer.Deserialize(s));
}
catch
{
expandState.Clear();
}
finally
{
s.Close();
}
}
expandState.Sort(); //order the keys so can be expanded from bottom up so pos matched grid row
for(int i = expandState.Count - 1; i >= 0; i--)
{
int pos = FindKeyValue(expandState[i]);
if(pos > -1)
{
this.gridDataBoundGrid1.ExpandAtRowIndex(pos + this.gridDataBoundGrid1.Model.Rows.HeaderCount + 1);
}
}
}
private void SaveState()
{
string fileName = "persistedExpandStates.xml";
int[] expandStates = (int[])expandState.ToArray(typeof(int));
XmlSerializer serializer = new XmlSerializer(typeof(int[]));
TextWriter writer = new StreamWriter(fileName);
serializer.Serialize(writer, expandStates);
writer.Close();
}
private int FindKeyValue(object key)
{
int col = this.gridDataBoundGrid1.Binder.NameToColIndex(keyColumn);
int row = -1;
for(int i = 0; i < this.parentTable.DefaultView.Count; ++i)
{
if(this.parentTable.DefaultView[i][keyColumn].Equals(key))
{
row = i;
break;
}
}
return row;
}
VB
Dim expandState As New ArrayList()
Private Sub gridDataBoundGrid1_RowExpanded(sender As Object, e As GridRowEventArgs)
''assumes a primary key value in "parentID" column
Dim col As Integer = Me.gridDataBoundGrid1.Binder.NameToColIndex(keyColumn)
Dim key As Integer = CInt(Me.gridDataBoundGrid1(e.RowIndex, col).CellValue)
expandState.Add(key)
End Sub ''gridDataBoundGrid1_RowExpanded
Private Sub gridDataBoundGrid1_RowCollapsed(sender As Object, e As GridRowEventArgs)
''assumes a primary key value in keyColumn column
Dim key As Integer = CInt(Me.gridDataBoundGrid1(e.RowIndex,
Me.gridDataBoundGrid1.Binder.NameToColIndex(keyColumn)).CellValue)
expandState.Remove(key)
End Sub ''gridDataBoundGrid1_RowCollapsed
Private Sub Form1_Closing(sender As Object, e As CancelEventArgs)
SaveState()
End Sub ''Form1_Closing
Private Sub LoadState()
Dim fileName As String = "persistedExpandStates.xml"
If File.Exists(fileName) Then
expandState.Clear()
Dim s As Stream = File.OpenRead(fileName)
Try
Dim serializer As New XmlSerializer(GetType(Integer()))
expandState = New ArrayList(CType(serializer.Deserialize(s), Integer()))
Catch
Finally
s.Close()
End Try
End If
expandState.Sort() ''order the keys so can be expanded from bottom up so pos matched grid row
Dim i As Integer
For i = expandState.Count - 1 To 0 Step -1
Dim pos As Integer = FindKeyValue(expandState(i))
If pos > - 1 Then
Me.gridDataBoundGrid1.ExpandAtRowIndex((pos + Me.gridDataBoundGrid1.Model.Rows.HeaderCount + 1))
End If
Next i
End Sub ''LoadState
Private Sub SaveState()
Dim fileName As String = "persistedExpandStates.xml"
Dim expandStates As Integer() = CType(expandState.ToArray(GetType(Integer)), Integer())
Dim serializer As New XmlSerializer(GetType(Integer()))
Dim writer = New StreamWriter(fileName)
serializer.Serialize(writer, expandStates)
writer.Close()
End Sub ''SaveState
Private Function FindKeyValue(key As Object) As Integer
Dim col As Integer = Me.gridDataBoundGrid1.Binder.NameToColIndex(keyColumn)
Dim row As Integer = - 1
Dim i As Integer
While i < Me.parentTable.DefaultView.Count
If Me.parentTable.DefaultView(i)(keyColumn).Equals(key) Then
row = i
Exit While
End If
End While
Return row
End Function ''FindKeyValue
Here is a sample that illustrates this:
http://websamples.syncfusion.com/samples/KB/Grid.Windows/PersistingExpandState/main.htm