2

プロパティが特定の値に設定されている特定TreeViewItemのものを見つけようとしています。Tag以下は、親が展開されFindNodeている場合、第1レベルのアイテムまたは他のレベルでのみ機能します。TreeViewItem以下の例では、「FFF」が展開されている場合FindNode、期待どおりに機能します。ContainerFromItemアイテムが作成されていないため、nullが返されると想定しています。すべてのTreeViewItemを強制的に作成する方法はありますか?

    <TreeView x:Name="__items">

        <TreeViewItem Header="AAA"
                      Tag="{x:Static my:Node.A}" />

        <TreeViewItem Header="BBB"
                      Tag="{x:Static my:Node.B}">

            <!-- Items will be added later. -->

        </TreeViewItem>

        <TreeViewItem Header="CCC"
                      Tag="{x:Static my:Node.C}" />

        <TreeViewItem Header="DDD"
                      Tag="{x:Static my:Node.D}" />

        <TreeViewItem Header="EEE"
                      Tag="{x:Static my:Node.E}" />

        <TreeViewItem Header="FFF"
                      Tag="{x:Static my:Node.F}">

            <TreeViewItem Header="GGG"
                          Tag="{x:Static my:Node.G}" />

            <TreeViewItem Header="HHH"
                          Tag="{x:Static my:Node.H}" />

        </TreeViewItem>

        <TreeViewItem Header="III"
                      Tag="{x:Static my:Node.I}" />

    </TreeView>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);    
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        TreeViewItem a = FindNode(__items.ItemContainerGenerator, __items.Items, Node.H); 
    }

    private TreeViewItem FindNode(ItemContainerGenerator gen, ItemCollection items, Node value)
    {
        TreeViewItem oResult = null;

        foreach (var oItem in items)
        {
            TreeViewItem oTreeViewItem = (TreeViewItem)gen.ContainerFromItem(oItem);

            if (oTreeViewItem == null) { continue; }

            if ((Node)oTreeViewItem.Tag == value) { oResult = oTreeViewItem; break; }

            if (oTreeViewItem.Items.Count > 0)
            {
                oResult = FindNode(oTreeViewItem.ItemContainerGenerator, oTreeViewItem.Items, value);

                if (oResult != null) { break; }
            }
        }
        return oResult;
    }

}

public enum Node { A, B, C, D, E, F, G, H, I, J, }

hbarckの回答に基づくと、正しいFindNode実装は次のとおりです。

    private TreeViewItem FindNode(ItemCollection items, Node value)
    {
        TreeViewItem oResult = null;

        foreach (var oItem in items)
        {
            TreeViewItem oTreeViewItem = (TreeViewItem)oItem;

            if ((Node)oTreeViewItem.Tag == value) { oResult = oTreeViewItem; break; }

            if (oTreeViewItem.Items.Count > 0)
            {
                oResult = FindNode(oTreeViewItem.Items, value);

                if (oResult != null) { break; }
            }
        }
        return oResult;
    }
4

2 に答える 2

1

はい、ItemsControlでアイテムを強制的に作成できます。ItemContainerGeneratorにアクセスし、(これは魔法です;))インターフェイスが明示的に実装されているため、IItemContainerGeneratorにキャストします。StartAtとGenerateNextを使用すると、アイテムを強制的に作成できます。

参照:ItemContainerGeneratorがnullを返すのはなぜですか? あなたはただすべてのアイテムのためにそれをする必要があります。

于 2012-05-07T14:01:04.477 に答える
0

TreeViewItemが存在することを確認する最も簡単な方法は、おそらくそれぞれにIsExpanded = "True"を設定し、TreeViewでIsVirtualizingをFalseに設定することです。好奇心から:ItemGeneratorを使用せず、代わりにItemsコレクションを直接繰り返すとどうなりますか?DataTemplateを使用していないため、ItemsコレクションにはXAMLファイルのハードコードされたアイテムが含まれている必要があると思います。

私は次のテストを行いました:

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <TreeView x:Name="TestTreeView">
        <TreeViewItem Header="Item 1">
            <TreeViewItem Header="Item 1 1"/>
            <TreeViewItem Header="Item 1 2"/>
        </TreeViewItem>
        <TreeViewItem Header="Item 2"/>
    </TreeView>
    <Button x:Name="TestButton" Click="TestButton_Click">Test</Button>
</StackPanel>
</Window>

とコードビハインド:

Class MainWindow 

    Private Sub TestButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)

        Stop
        For Each t As TreeViewItem In Me.TestTreeView.Items
            Debug.Print("Item: {0}, Child count:{1}", t.Header, t.Items.Count)
        Next
    End Sub
End Class

デバッグウィンドウの出力は次のとおりです。

Item: Item 1, Child count:2
Item: Item 2, Child count:0

これは、子レベルでもアイテムがインスタンス化され、反復できることを意味します。おそらく邪魔になるのはItemContainerGeneratorです。これは、実際にはDataTemplatesを使用している場合にのみ必要です。また、すべてのアイテムをインスタンス化するには、ウィンドウのLoadedイベントが終了するまで待つ必要があります。

于 2012-05-07T21:24:50.700 に答える