21


4

NETアプリケーションでツリービューコントロールのスクロール位置を維持する方法を教えてください。 例えば、私はツリービューコントロールを持っていて、そこにさまざまなノードを追加してそれらを一番下に追加するプロセスを経ています。 この過程で、ツリービューをスクロールしてさまざまなノードを表示できます。 問題は、プロセスが完了すると、ツリービューが一番下までスクロールすることです。

treenode.Expand()を呼び出すことで、ここから軌道に乗っているように見えます。 親ノードが展開されると、それはフォーカスを得ます。

これを回避する方法はありますか? プロセスの実行中に特定のノードを見ているのであれば、プロセスが完了したときにそのノードに飛び乗ってはいけません。

9 Answer


26


私はVBの人ではありませんが、C#ではこのようにしています。

いくつかのWin32ネイティブ関数:

[DllImport("user32.dll",  CharSet = CharSet.Unicode)]
public static extern int GetScrollPos(IntPtr hWnd、int nBar);

[DllImport("user32.dll",  CharSet = CharSet.Unicode)]
public static extern int SetScrollPos(IntPtr hWnd、int nBar、int nPos、bool bRedraw);

プライベート定数int SB_HORZ = 0x0。プライベート定数int SB_VERT = 0x1。

現在のスクロール位置のポイントを返すメソッド

private Point GetTreeViewScrollPos(TreeView treeView){新しいPointを返す(GetScrollPos((int)treeView.Handle、SB_HORZ)、GetScrollPos((int)treeView.Handle、SB_VERT)); }

*スクロール位置を設定する方法

プライベートvoid SetTreeViewScrollPos(TreeViewツリービュー、ポイントscrollPosition){SetScrollPos((IntPtr)treeView.Handle、SB_HORZ、scrollPosition.X、true); SetScrollPos((IntPtr)treeView.Handle、SB_VERT、scrollPosition.Y、true); }

それからあなたがあなたの木を更新するとき、次のことをしなさい:

BeginUpdate(); Point ScrollPos = GetTreeViewScrollPos(treeMain);
// write your update code here
SetTreeViewScrollPos(treeMain、ScrollPos); EndUpdate();


17


私はそれを考え出したと思います:

  1. ツリービューの一番上にあるノードを取得します。

  2. 親ノードを展開します。

  3. 前に一番上にあったノードを表示状態にします。

_ _

If treeNodeParent.IsExpanded = False Then
    Dim currentNode As TreeNode = TreeViewHosts.GetNodeAt(0, 0)
    treeNodeParent.Expand()
    currentNode.EnsureVisible()
End If

_ _

これを行うためのより良い方法はありますか?


6


外部関数なしでスクロール位置を保存することができるもう一つの方法はツリーのTopNodeプロパティを使うことです…​

TopNodeは、ツリービューコントロール内の最初の完全に見えるツリーノードを取得または設定します。

単にノードを展開して最上位ノードを保持したい場合は、次のようにします。

TreeNode topNode = m_Tree.TopNode; treenode.Expand(); m_Tree.TopNode = topNode;

それ以外の場合、ファイル構造の更新など、ツリーを再構築している場合は、次の方法を使用できます。

ツリーを消去する前に、最上位ノードへのフルパスを保存します。

ストリングtopNodePath = null。 TreeNode topNode = null。 if(m_Tree.TopNode!= null){topNodePath = m_Tree.TopNode.FullPath; }

m_Tree.Clear();

ノードを追加した後、topNodePathに対してFullPathを確認します。

nodes.Add(node)if((topNodePath!= null)

すべてのノードを追加したら、ツリーのTopNodeプロパティを更新します。

if(topNode!= null){m_Tree.TopNode = topNode; }

私は、選択され拡張されたノードにも同様の手法を使います。 SelectedNodeは、上に示したTopNodeとほぼ同じように機能します。 拡張ノードの場合、再帰関数を使用して子ノードをループ処理し、拡張ノードのパスをリストに追加します。 それから子供が加えられた後彼らの道に基づいてそれらを拡大する。

もちろん、同じ名前の兄弟ノードがたくさんある場合、これはうまくいかないかもしれません:-)


2


SetTreeViewScrollPosition(point)`を `BeginUpdate`と EndUpdate`でラップするのが最善の方法です…​

private void treeViewXml1_Scroll(object sender, ScrollEventArgs e)
{
    Point point = treeViewXml1.GetTreeViewScrollPosition();

    treeViewXml2.BeginUpdate();
    treeViewXml2.SetTreeViewScrollPosition(point);
    treeViewXml2.EndUpdate();
}

private void treeViewXml2_Scroll(object sender, ScrollEventArgs e)
{
    Point point = treeViewXml2.GetTreeViewScrollPosition();

    treeViewXml1.BeginUpdate();
    treeViewXml1.SetTreeViewScrollPosition(point);
    treeViewXml1.EndUpdate();
}


1


スクロール自体が更新されたのと同じ問題がありましたが、ツリービューの内容はスクロールされませんでした。 これは `SetScrollPos()`の周りに `BeginUpdate()`と `EndUpdate()`を追加することで簡単に修正されました。

this.hierarchyTreeView.BeginUpdate();
SetScrollPos(this.hierarchyTreeView.Handle, SB_VERT, 5, true);
this.hierarchyTreeView.EndUpdate();


0


myTreeView.Nodes [0] .EnsureVisible();


0


それは、TreeViewExtensionとしてのStefan Koellからの美しいレスポンスの改訂版です。(完全なソリューション)

システムを使用する。 System.Runtime.InteropServicesを使用します。 System.Windowsを使用します。 System.Windows.Controlsを使用します。 System.Windows.Interopを使用します。 System.Windows.Mediaを使用する。

public static class TreeViewExtension {#region定数

private const int ScrollBarHorizo​​ntal = 0x0;

private const int ScrollBarVertical = 0x1;

#endregion

#regionパブリックメソッドと演算子

[DllImport( "user32.dll"、CharSet = System.Runtime.InteropServices.CharSet.Auto)] public static extern int GetScrollPos(int hWnd、int nBar);

public static Point ScrollPosition(このTreeViewのツリービュー){新しいポイントを返す(GetScrollPos((int)treeView.Handle()、ScrollBarHorizo​​ntal)、GetScrollPos((int)treeView.Handle()、ScrollBarVertical)); }

public static void ScrollTo(このTreeViewのtreeView、PointのscrollPosition){SetScrollPos(treeView.Handle()、ScrollBarHorizo​​ntal、(int)scrollPosition.X、true); SetScrollPos(treeView.Handle()、ScrollBarVertical、(int)scrollPosition.Y、true); }

[DllImport( "user32.dll")] public static extern int SetScrollPos(IntPtr hWnd、int nBar、int nPos、bool bRedraw);

#endregion

#regionメソッド

プライベートstatic IntPtrハンドル(このビジュアルツリービュー){var handle = IntPtr.Zero; HwndSourceとしてvar hwndSource = PresentationSource.FromVisual(treeView)。 if(hwndSource!= null){handle = hwndSource.Handle; }

ハンドルを返す。 }

#endregion}

おそらくそれはあなたの仕事を単純化します;-)


0


これはうまくいきます。 TopNodeを保存し、以下の後に復元します。

this.treeView.BeginUpdate(); TreeNode topNode = this.treeView.TopNode;

// your code
this.treeView.Sort(); this.treeView.SelectedNode = auxNode;

this.treeView.TopNode = topNode; this.treeView.EndUpdate();


-3


最善の方法は、UpdatePanelを使用し、その中にツリービュータグをネストすることです。 例えば、


それは私のために働いた、そして私はそれがあなたの問題を解決することを願っている。