Here, the working code example synchronizes the (single) selection in TreeView, ListView, and ComboBox using lambda expressions in the dictionary, where the key in the dictionary is a control and the value of each key is Action<int>.
Where I am stuck is that I get several repetitions of the code that sets the selection in various controls in such an unexpected way: it is not recursive: there is no StackOverFlow error; but I would like to find out why the current strategy for preventing multiple selection of the same control does not work.
Perhaps the real problem is the difference between the selection update initiated by the end user and the selection update initiated by the code that synchronizes the other controls?
Note. I experimented with using delegates and delegate forms, such as Action<T>to insert executable code into dictionaries: “I’ll learn better”, creating “problems” for programming and realizing them while studying the “golden words” of lights like Skeet, MacDonald, Liberty, Troelsen, Sells, Richter.
Note. When adding to this question / code for the "deep background" this statement is about how I did something in pre C # 3.0, when it seemed to me that I needed to use explicit measures to prevent recursion when synchronizing the selection.
Code: Suppose that for standard WinForms, TreeView, ListView, ComboBox all have the same set of records (i.e., TreeView has only root nodes, and ListView has one column in the details view).
private Dictionary<Control, Action<int>> ControlToAction = new Dictionary<Control, Action<int>>();
private void Form1_Load(object sender, EventArgs e)
{
ControlToAction.Add(treeView1, (i => { treeView1.SelectedNode = treeView1.Nodes[i]; }));
ControlToAction.Add(listView1, (i => { listView1.Items[i].Selected = true; }));
ControlToAction.Add(comboBox1, (i => { comboBox1.SelectedIndex = i; }));
}
private void synchronizeSelection(int i, Control currentControl)
{
foreach(Control theControl in ControlToAction.Keys)
{
if (theControl == currentControl) continue;
Console.WriteLine(theControl.Name + " synchronized");
ControlToAction[theControl](i);
}
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
synchronizeSelection(e.Node.Index, treeView1);
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedIndices.Count > 0)
{
synchronizeSelection(listView1.SelectedIndices[0], listView1);
}
}
private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex > -1)
{
synchronizeSelection(comboBox1.SelectedIndex, comboBox1);
}
}
background: pre C # 3.0
It seems that in the previous days of C # 3.0, I always used a boolean flag to prevent recursion when updating multiple controls. For example, to synchronize the TreeView and ListView, I usually had this code: provided that each item in the ListView was synchronized with the root level of the TreeView node using a common index:
private bool dontRecurse = false;
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if(dontRecurse) return;
dontRecurse = true;
listView1.Items[e.Node.Index].Selected = true;
dontRecurse = false;
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if(dontRecurse) return
if (listView1.SelectedIndices.Count > 0)
{
dontRecurse = true;
treeView1.SelectedNode = treeView1.Nodes[listView1.SelectedIndices[0]];
dontRecurse = false;
}
}
, , - FrameWork 3 ~ 3.5, , , ( , TreeView ListView). , , .