我看过here和here以及许多其他地方,但我似乎无法让ItemContainerGenerator.ContainerFromItem方法在WPF TreeView上工作!我试图传递我想要看到的实际项目,但是没有取得任何进展,我只是尝试在我的TreeView中获得第一个项目。下面是我的示例代码:
private static bool ExpandAndSelectItem(ItemsControl parentContainer, object itemToSelect)
{
// This doesn't work.
parentContainer.BringIntoView();
// May be virtualized, bring into view and try again.
parentContainer.UpdateLayout();
parentContainer.ApplyTemplate();
TreeViewItem topItem = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(parentContainer.Items[0]);
// Can't find child container unless the parent node is Expanded once
if ((topItem != null) && !topItem.IsExpanded)
{
topItem.IsExpanded = true;
parentContainer.UpdateLayout();
}
}如您所见,我试图调用许多“更新”方法,以使TreeView成为“可见的”和“可访问的”。问题是,除非第一个ContainerFromItem()是展开的,否则您就不能使用TreeViewItem,但是在ContainerFromItem()工作之前,我无法抓取TreeViewItem来扩展它!
另一件有趣的事情是:当我打开这个窗口(它是一个UserControl)时,ContainerFromItem()返回空,但是如果我关闭窗口并重新打开它,ContainerFromItem()将开始返回非空。有什么事件我应该寻找或强迫开火吗?
发布于 2014-01-02 23:07:45
原来我要找的那件事是“装好的”。我只是在XAML中将一个事件处理程序附加到我的treeview上,并在该事件处理程序中调用了我的逻辑。
<TreeView x:Name="MyTreeView"
Margin="0,5,0,5"
HorizontalAlignment="Left"
BorderThickness="0"
FontSize="18"
FontFamily="Segoe WP"
MaxWidth="900"
Focusable="True"
Loaded="MyTreeView_Load">
...
</TreeView>事件处理程序:
private void MyTreeView_Load(object sender, RoutedEventArgs e)
{
ShowSelectedThing(MyTreeView, ThingToFind);
}
// Gotta call the TreeView an ItemsControl to cast it between TreeView and TreeViewItem
// as you recurse
private static bool ShowSelectedThing(ItemsControl parentContainer, object ThingToFind)
{
// check current level of tree
foreach (object item in parentContainer.Items)
{
TreeViewItem currentContainer = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item);
if ((currentContainer != null) && (item == ThingToFind)
{
currentContainer.IsSelected = true;
currentContainer.BringIntoView();
return true;
}
}
// item is not found at current level, check the kids
foreach (object item in parentContainer.Items)
{
TreeViewItem currentContainer = (TreeViewItem)parentContainer.ItemContainerGenerator.ContainerFromItem(item);
if ((currentContainer != null) && (currentContainer.Items.Count > 0))
{
// Have to expand the currentContainer or you can't look at the children
currentContainer.IsExpanded = true;
currentContainer.UpdateLayout();
if (!ShowSelectedThing(currentContainer, ThingToFind))
{
// Haven't found the thing, so collapse it back
currentContainer.IsExpanded = false;
}
else
{
// We found the thing
return true;
}
}
}
// default
return false;
}希望这能帮上忙。有时候在现实世界里,有着苛刻的客户,奇怪的要求和很短的截止时间,你必须要黑!
发布于 2017-07-18 08:27:15
当容器生成器的状态为“NotStarted”或“ContainersGenerating”时,您将找不到容器。
使用此方法查找数据项的容器。
private static async Task<TreeViewItem> FindItemContainer(ItemsControl itemsControl, object item)
{
var generator = itemsControl.ItemContainerGenerator;
if (generator.Status != GeneratorStatus.ContainersGenerated)
{
var tcs = new TaskCompletionSource<object>();
EventHandler handler = null;
handler = (s, e) =>
{
if (generator.Status == GeneratorStatus.ContainersGenerated)
{
generator.StatusChanged -= handler;
tcs.SetResult(null);
}
else if (generator.Status == GeneratorStatus.Error)
{
generator.StatusChanged -= handler;
tcs.SetException(new InvalidOperationException());
}
};
generator.StatusChanged += handler;
if (itemsControl is TreeViewItem tvi)
tvi.IsExpanded = true;
itemsControl.UpdateLayout();
await tcs.Task;
}
var container = (TreeViewItem)generator.ContainerFromItem(item);
if(container == null)
{
foreach (var parentItem in itemsControl.Items)
{
var parentContainer = (TreeViewItem)generator.ContainerFromItem(parentItem);
container = await FindItemContainer(parentContainer, item);
if (container != null)
return container;
}
}
return container;
}https://stackoverflow.com/questions/20863666
复制相似问题