Lấy cảm hứng từ câu trả lời của Fëanor, tôi đã cố gắng làm cho TreeViewItem
dễ dàng truy cập được đối với mọi mục dữ liệu mà TreeViewItem
đã được tạo.
Ý tưởng là để thêm một lĩnh vực -typed TreeViewItem
với mô hình xem, cũng tiếp xúc thông qua một giao diện, và có TreeView
tự động cư nó bất cứ khi nào container TreeViewItem
được tạo ra.
Điều này được thực hiện bằng cách phân lớp TreeView
và đính kèm sự kiện vào ItemContainerGenerator
, ghi lại TreeViewItem
bất cứ khi nào được tạo. Gotchas bao gồm một thực tế là TreeViewItem
s được tạo ra một cách lười biếng, do đó, có thể thực sự không phải là có sẵn tại một số thời điểm nhất định.
Kể từ khi đăng câu trả lời này, tôi đã phát triển thêm và sử dụng nó trong một thời gian dài trong một dự án. Không có vấn đề cho đến nay, khác với thực tế là điều này vi phạm MVVM (nhưng cũng giúp bạn tiết kiệm một tấn boilerplate cho các trường hợp đơn giản). Nguồn here.
Cách sử dụng
Chọn phụ huynh của mục đã chọn và sụp đổ nó, đảm bảo rằng đó là trong giao diện:
...
var selected = myTreeView.SelectedItem as MyItem;
selected.Parent.TreeViewItem.IsSelected = true;
selected.Parent.TreeViewItem.IsExpanded = false;
selected.Parent.TreeViewItem.BringIntoView();
...
khai báo:
<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; }
...
}
Mã
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; }
}
Nguồn
2012-03-26 13:33:13
@romkyns: Cái gì? Câu hỏi này có * không có gì * để làm với việc theo dõi mục đã chọn. –
@romkyns: Vâng, bạn không nên lấy TreeViewItem ngay từ đầu, vì vậy nó không thực sự quan trọng nếu nó khó làm hay không. –
@ H.B. Đó cũng có thể là như vậy ... có thể [bạn có thể giúp tôi làm điều này mà không có TreeViewItem] (http://stackoverflow.com/questions/9761336/whats-the-wpf-way-to-mark-a-command-as- không có sẵn-chỉ-nếu-cha mẹ-of-a-tree)? –