今回は選択されたノードの履歴をとります。これによってボタンを押すと前に選択されていたノードに移動することができます。
まず新しくノードが選択されるときは現在選択されているノードをpreSelectedNodesに格納します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class SyncTreeViewEx : SyncTreeView { public List<TreeNodeEx> preSelectedNodes = new List<TreeNodeEx>(); public List<TreeNodeEx> afterSelectedNodes = new List<TreeNodeEx>(); IsNoInsertHistory = false; protected override void OnBeforeSelect(BeforeSelectArgs e) { base.OnBeforeSelect(e); if (!e.Cancel && !IsNoInsertHistory && !Form1.ignoreSelectedNodeChange) { var selectedNode = this.SelectedNode; if (selectedNode != null) preSelectedNodes.Insert(0, selectedNode); afterSelectedNodes.Clear(); } } } |
スプリットボタンを押すと前後の選択されていたノードを選択することができます。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void selectPrevToolStripSplitButton_ButtonClick(object sender, EventArgs e) { syncTreeViewEx1.SelectFromPreSelectedNodes(); } private void selectAfterToolStripSplitButton_ButtonClick(object sender, EventArgs e) { syncTreeViewEx1.SelectFromAfterSelectedNodes(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class SyncTreeViewEx : SyncTreeView { public void SelectFromPreSelectedNodes() { if (preSelectedNodes.Count == 0) return; TreeNodeEx oldNode = this.SelectedNode; IsNoInsertHistory = true; var node = preSelectedNodes[0]; this.SelectedNode = node; preSelectedNodes.RemoveAt(0); afterSelectedNodes.Insert(0, oldNode); IsNoInsertHistory = false; } public void SelectFromAfterSelectedNodes() { if (afterSelectedNodes.Count == 0) return; TreeNodeEx oldNode = this.SelectedNode; IsNoInsertHistory = true; var node = afterSelectedNodes[0]; this.SelectedNode = node; afterSelectedNodes.RemoveAt(0); preSelectedNodes.Insert(0, oldNode); IsNoInsertHistory = false; } } |
ノードが削除されるときは履歴からも削除されなければならないので、そのようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class SyncTreeViewEx : SyncTreeView { public new void DeleteNode(TreeNodeEx nodeEx) { List<TreeNodeEx> deletingNodes = this.GetTreeNodeExs(nodeEx); IsNoInsertHistory = true; base.DeleteNode(nodeEx); IsNoInsertHistory = false; afterSelectedNodes = afterSelectedNodes.Except(deletingNodes).ToList(); preSelectedNodes = preSelectedNodes.Except(deletingNodes).ToList(); } } |
それから新しくファイルが読み込まれたときも履歴は削除されなければなりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class SyncTreeViewEx : SyncTreeView { public void ClearSelectHistory() { preSelectedNodes.Clear(); afterSelectedNodes.Clear(); } } public partial class Form1 : Form { void OpenFile(string filePath) { // ファイルを正常に開くことができたら・・・ syncTreeViewEx1.ClearSelectHistory(); syncTreeViewEx2.ClearSelectHistory(); } } |
スプリットボタンが展開されると格納されたノードのラベルが表示されるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { private void selectPrevToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectPrevToolStripSplitButton.DropDownItems.Clear(); foreach (var nodeEx in syncTreeViewEx1.preSelectedNodes) { if(nodeEx != null) selectPrevToolStripSplitButton.DropDownItems.Add(nodeEx.Text); } } private void selectAfterToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectAfterToolStripSplitButton.DropDownItems.Clear(); foreach (var nodeEx in syncTreeViewEx1.afterSelectedNodes) { if (nodeEx != null) selectAfterToolStripSplitButton.DropDownItems.Add(nodeEx.Text); } } } |
ただ項目が表示されても選択したときに反応しないのでは意味がありません。選択すると対応するノードを選択できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
public partial class Form1 : Form { private void selectPrevToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectPrevToolStripSplitButton.DropDownItems.Clear(); foreach (var nodeEx in syncTreeViewEx1.preSelectedNodes) { if (nodeEx != null) { string str = String.Format("Page {0}: {1}", GetData(nodeEx).pageNumber, nodeEx.Text); ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = str; item.Tag = nodeEx; item.Click += Item_Click1; selectPrevToolStripSplitButton.DropDownItems.Add(item); } } void Item_Click1(object sender1, EventArgs e1) { ToolStripMenuItem item = (ToolStripMenuItem)sender1; syncTreeViewEx1.SelectFromPreSelectedNodes((TreeNodeEx)item.Tag); } } private void selectAfterToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectAfterToolStripSplitButton.DropDownItems.Clear(); foreach (var nodeEx in syncTreeViewEx1.afterSelectedNodes) { if (nodeEx != null) { string str = String.Format("Page {0}: {1}", GetData(nodeEx).pageNumber, nodeEx.Text); ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = str; item.Tag = nodeEx; item.Click += Item_Click1; selectAfterToolStripSplitButton.DropDownItems.Add(item); } } void Item_Click1(object sender1, EventArgs e1) { ToolStripMenuItem item = (ToolStripMenuItem)sender1; syncTreeViewEx1.SelectFromAfterSelectedNodes((TreeNodeEx)item.Tag); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
public class SyncTreeViewEx : SyncTreeView { public void SelectFromPreSelectedNodes(TreeNodeEx nodeEx) { IsNoInsertHistory = true; int index = preSelectedNodes.IndexOf(nodeEx); if (index != -1) { var moves = preSelectedNodes.Take(index + 1).ToList(); preSelectedNodes = preSelectedNodes.Skip(index + 1).ToList(); afterSelectedNodes.Insert(0, SelectedNode); foreach (var node in moves) { afterSelectedNodes.Insert(0, node); } afterSelectedNodes.RemoveAt(0); SelectedNode = moves.Last(); } IsNoInsertHistory = false; } public void SelectFromAfterSelectedNodes(TreeNodeEx nodeEx) { IsNoInsertHistory = true; int index = afterSelectedNodes.IndexOf(nodeEx); if (index != -1) { var moves = afterSelectedNodes.Take(index + 1).ToList(); afterSelectedNodes = afterSelectedNodes.Skip(index + 1).ToList(); preSelectedNodes.Insert(0, SelectedNode); foreach (var node in moves) { preSelectedNodes.Insert(0, node); } preSelectedNodes.RemoveAt(0); SelectedNode = moves.Last(); } IsNoInsertHistory = false; } } |
こういう問題もあるので、(同じノードを何でも選択する)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class SyncTreeViewEx : SyncTreeView { List<TreeNodeEx> preSelectedNodes = new List<TreeNodeEx>(); // privateに List<TreeNodeEx> afterSelectedNodes = new List<TreeNodeEx>(); public List<TreeNodeEx> PreSelectedNodes // データが改ざんされるのを防ぐ { get { return preSelectedNodes.ToList(); } } public List<TreeNodeEx> AfterSelectedNodes // データが改ざんされるのを防ぐ { get { return afterSelectedNodes.ToList(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
public partial class Form1 : Form { private void selectPrevToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectPrevToolStripSplitButton.DropDownItems.Clear(); var preSelectedNodes = syncTreeViewEx1.PreSelectedNodes.Distinct(new TreeNodeExEqualityComparer()).ToList(); // ダブりを排除する preSelectedNodes.Remove(syncTreeViewEx1.SelectedNode); preSelectedNodes = preSelectedNodes.Take(10).ToList(); foreach (var nodeEx in preSelectedNodes) { if (nodeEx != null) { string str = String.Format("Page {0}: {1}", GetData(nodeEx).pageNumber, nodeEx.Text); ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = str; item.Tag = nodeEx; item.Click += Item_Click1; selectPrevToolStripSplitButton.DropDownItems.Add(item); } } void Item_Click1(object sender1, EventArgs e1) { ToolStripMenuItem item = (ToolStripMenuItem)sender1; syncTreeViewEx1.SelectFromPreSelectedNodes((TreeNodeEx)item.Tag); } } private void selectAfterToolStripSplitButton_DropDownOpening(object sender, EventArgs e) { selectAfterToolStripSplitButton.DropDownItems.Clear(); var afterSelectedNodes = syncTreeViewEx1.AfterSelectedNodes.Distinct(new TreeNodeExEqualityComparer()).ToList(); // ダブりを排除する afterSelectedNodes.Remove(syncTreeViewEx1.SelectedNode); afterSelectedNodes = afterSelectedNodes.Take(10).ToList(); foreach (var nodeEx in afterSelectedNodes) { if (nodeEx != null) { string str = String.Format("Page {0}: {1}", GetData(nodeEx).pageNumber, nodeEx.Text); ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = str; item.Tag = nodeEx; item.Click += Item_Click1; selectAfterToolStripSplitButton.DropDownItems.Add(item); } } void Item_Click1(object sender1, EventArgs e1) { ToolStripMenuItem item = (ToolStripMenuItem)sender1; syncTreeViewEx1.SelectFromAfterSelectedNodes((TreeNodeEx)item.Tag); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class TreeNodeExEqualityComparer : IEqualityComparer<TreeNodeEx> { public bool Equals(TreeNodeEx x, TreeNodeEx y) { if (x == null && y == null) return true; if (x == null || y == null) return false; return x.Data == y.Data; } public int GetHashCode(TreeNodeEx p) { return p.Data.GetHashCode(); } } |
これでドロップダウンリストのなかに重複した項目は表示されなくなります。