It sounds like you just need to run your algorithm again when the collection changes. Since you are testing the ItemContainerGenerator.Status
property, the algorithm may not run. You may want to consider listening to the StatusChanged
event, and when it changes to ContainersGenerated
run the algorithm again.
Thank you Abe, your second comment lead me to my solution!
I added tabItem.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
to each iteration of the loop.
I would still be interested in learning if anyone else finds a way around this without refreshing each tabItem on every change. I tried refreshing the entire tab control at the end of the loop but that only worked for closing tabs, not adding them. I know that Panel.ZIndex is getting set correctly, it's just not honoring that property when rendering.
EDIT: The above line of code was causing an unusual flicker when Dragging/Dropping the tabs that would briefly show the tab behind the one being dragged. I moved the code to a separate function and called it at a lower dispatcher priority and this fixed the problem. Final code is below:
private void PrimaryTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
TabControl tabControl = sender as TabControl;
tabControl.Dispatcher.BeginInvoke(
new Action(() => UpdateZIndex(sender as TabControl)),
DispatcherPriority.Background);
}
}
private void UpdateZIndex(TabControl tabControl)
{
ItemContainerGenerator icg = tabControl.ItemContainerGenerator;
if (icg.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
{
foreach (object o in tabControl.Items)
{
UIElement tabItem = icg.ContainerFromItem(o) as UIElement;
if (tabItem != null)
{
// Set ZIndex
Panel.SetZIndex(tabItem, (o == tabControl.SelectedItem ? 100 :
90 - tabControl.Items.IndexOf(o)));
}
}
}
}