Is it possible in WinForms to bind controls to hierarchical data?
For example, there is the following xml:

<data> <level1 name='l11'> <level2 name='l12'> <level3 name='l13' /> </level2> </level1> <level1 name='l21'> <level2 name='l22'> <level3 name='l23' /> </level2> </level1> </data> 

It is necessary to display all values ​​of level1 name in one DataGridView. All level2 name output to another DataGridView. And all level3 name - in the third.
Values ​​should be displayed with respect to the hierarchy. For example, if the current line in the DataGridView for level1 is l11, then in the DataGridView for level2, l12 is output.
Values ​​in each of the DataGridView can be added / deleted / edited and at the same time the modified xml should be immediately displayed.

enter image description here

  • one
    This is an example for separate contours and a fixed level of hierarchy. What you describe is the usual Master-Details (with three fixed levels instead of two). Under the hierarchical datasors usually mean a tree structure of homogeneous elements - folders on the disk, for example. And under the hierarchical controls there are integral controls without a previously known level of hierarchy (TreeView, for example. And not three separate grids) - PashaPash
  • "hierarchical datasors usually imply tree structures of homogeneous elements" - such structures are stored in the form of tables with id and parentId. binding also works. An example of the answer - here - Stack
  • There is hierarchical data, but non-hierarchical mapping - there is no visual connection at a distance farther than one level. to get from level 0 to level 2, you need to find and select an intermediate line with your hands. And not just open the current item, as in the tree view. Imagine that there are several thousand lines there - and it will become obvious that such a view does not allow you to see the hierarchy and move freely along it. (Someone has already minus, especially without understanding). - PashaPash
  • "It's not easy to open the current item, as in the tree view." - that's just how difficult it is with a treeview when there are many levels try to find the most nested folder in the explorer) obviously, it is much easier to work with lists. and you can make a treelist. and the question was about binding to the tables "on itself" - i.e. when there is a nested relation. and as the example in the answer shows, it is possible. and about a binding to treeview then I will write. - Stack

1 answer 1

In WinForms, controls have DataSource and DataMember properties that allow you to bind controls to a data source.
To create an xml editor in WinForms, as shown in the figure, the following code is sufficient.

 using System; using System.Data; using System.Drawing; using System.Windows.Forms; using System.Linq; using System.IO; class Program { [STAThread] static void Main(string[] args) { var d = Model.Create(); var l1 = new DataGridView() { Bounds = new Rectangle(0, 0, 249, 400), BorderStyle = BorderStyle.None, ColumnHeadersVisible = false, DataSource = d, DataMember = "level1" }; var l2 = new DataGridView() { Bounds = new Rectangle(250, 0, 249, 199), BorderStyle = BorderStyle.None, ColumnHeadersVisible = false, DataSource = d, DataMember = "level1.level1_level2" }; var l3 = new DataGridView() { Bounds = new Rectangle(250, 200, 249, 200), BorderStyle = BorderStyle.None, ColumnHeadersVisible = false, DataSource = d, DataMember = "level1.level1_level2.level2_level3" }; var t = new RichTextBox() { Bounds = new Rectangle(501, 0, 349, 400), BorderStyle = BorderStyle.None, ReadOnly = true, Text = Model.GetXml(d) }; var f = new Form() { ClientSize = new Size(850, 400), FormBorderStyle = FormBorderStyle.FixedDialog, MaximizeBox = false, MinimizeBox = false }; f.Controls.AddRange(new Control[] { l3, l2, l1, t }); foreach (var g in f.Controls.OfType<DataGridView>()) g.BindingContext[g.DataSource, g.DataMember].CurrentItemChanged += (s, e) => t.Text = Model.GetXml(d); f.ShowDialog(); } class Model { public static object Create() { var xml = @" <data> <level1 name='l1'> <level2 name='l2'> <level3 name='l3' /> </level2> </level1> </data>"; var ds = new DataSet(); ds.ReadXml(new StringReader(xml)); return ds; } public static string GetXml(object model) { var ds = model as DataSet; var sw = new StringWriter(); ds.WriteXml(sw); return sw.ToString(); } } }