Fëanor の回答に触発されて、作成されTreeViewItem
たすべてのデータ項目に簡単にアクセスできるようにしTreeViewItem
ました。
アイデアは、TreeViewItem
型指定されたフィールドをビューモデルに追加し、これもインターフェイスを介して公開し、コンテナが作成さTreeView
れるたびに自動的に入力することです。TreeViewItem
これは、イベントをサブクラス化TreeView
して にアタッチすることによって行われます。これは、作成されるたびにItemContainerGenerator
を記録します。TreeViewItem
落とし穴には、 が遅延して作成されるという事実が含まれているTreeViewItem
ため、特定の時間に使用できるものがない可能性があります。
この回答を投稿して以来、私はこれをさらに発展させ、1 つのプロジェクトで長い間使用してきました。これがMVVMに違反しているという事実を除いて、これまでのところ問題はありません(ただし、単純なケースではボイラープレートを大量に節約できます)。ソースはこちら。
使用法
選択したアイテムの親を選択して折りたたんで、それがビューにあることを確認します。
...
var selected = myTreeView.SelectedItem as MyItem;
selected.Parent.TreeViewItem.IsSelected = true;
selected.Parent.TreeViewItem.IsExpanded = false;
selected.Parent.TreeViewItem.BringIntoView();
...
宣言:
<Window ...
xmlns:tvi="clr-namespace:TreeViewItems"
...>
...
<tvi:TreeViewWithItem x:Name="myTreeView">
<HierarchicalDataTemplate DataType = "{x:Type src:MyItem}"
ItemsSource = "{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</tvi:TreeViewWithItem>
...
</Window>
class MyItem : IHasTreeViewItem
{
public string Name { get; set; }
public ObservableCollection<MyItem> Children { get; set; }
public MyItem Parent;
public TreeViewItem TreeViewItem { get; set; }
...
}
コード
public class TreeViewWithItem : TreeView
{
public TreeViewWithItem()
{
ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
}
private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
var generator = sender as ItemContainerGenerator;
if (generator.Status == GeneratorStatus.ContainersGenerated)
{
int i = 0;
while (true)
{
var container = generator.ContainerFromIndex(i);
if (container == null)
break;
var tvi = container as TreeViewItem;
if (tvi != null)
tvi.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
var item = generator.ItemFromContainer(container) as IHasTreeViewItem;
if (item != null)
item.TreeViewItem = tvi;
i++;
}
}
}
}
interface IHasTreeViewItem
{
TreeViewItem TreeViewItem { get; set; }
}