Reputation: 1252
I have Tab Control which has many tab items, I am checking Data Grid Items Count while closing tab items. For the first time it works fine(I mean in first iteration). After closing one tab item, in second iteration sellDtg is null. Does anyone know why it is happening? I am concerning that this is UI problem, layout is not being refreshed. Please help me or show direction.
while (tc.HasItems)
{
TabItem ti = tc.SelectedItem as TabItem;
if (ti.Header == "Продажа")
{
Microsoft.Windows.Controls.DataGrid sellDtg = FindChild<Microsoft.Windows.Controls.DataGrid>(tc, "SellDataGrid");
if (sellDtg.Items.Count > 0)
{
Sell sl = new Sell();
if (Sell.basketfromSellDateListBox == false)
{
sl.ClearBasket(sellDtg);
Sell.ClearFromSellBasket((int)sellDtg.Tag);
}
}
}
if (ti != null)
tc.Items.Remove(ti);
}
Thanks in advance!!!
Upvotes: 1
Views: 617
Reputation: 30498
I am going to assume your FindChild
method uses the VisualTreeHelper
to find its children.
In the first iteration, the TabItem
's Content
has been through a layout pass, and is visible. This means that the TabItem
's Content
will be in the visual tree.
However, for the other tab items, their Content
hasn't been through a layout pass (it is only added to the visual tree when it's parent gets selected, and this has to then go through a layout/render pass), and won't be in the visual tree.
There are a couple of ways to get the child content of a TabItem
that hasn't been through a layout pass as the selected tab:
1) You can try using the LogicalTreeHelper
to find the Grid
you're looking for (and you will likely have to search the Content
of the TabItem
, not the TabControl
).
2) You can take your code out of the while loop, and do a callback on the dispatcher at the Loaded priority:
void RemoveAllItems()
{
if (!tc.HasItems) return;
TabItem ti = tc.SelectedItem as TabItem;
if (ti.Header == "Продажа")
{
var sellDtg = FindChild<Microsoft.Windows.Controls.DataGrid>(tc, "SellDataGrid");
if (sellDtg.Items.Count > 0)
{
Sell sl = new Sell();
if (Sell.basketfromSellDateListBox == false)
{
sl.ClearBasket(sellDtg);
Sell.ClearFromSellBasket((int)sellDtg.Tag);
}
if (ti != null)
tc.Items.Remove(ti);
}
}
Dispatcher.BeginInvoke(new Action(RemoveAllItems), DispatcherPriority.Loaded);
}
If you use the second method, you will likely be able to see the tab items removed one at a time, which may be something you don't want to see.
Upvotes: 0
Reputation: 248
I've written a simple FindChildLogical
function in analogy for LogicalTreeHelper
below:
public static T FindChildLogical<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
if (parent == null) return null;
var child = LogicalTreeHelper.FindLogicalNode(parent, childName);
return (T)child;
}
and you call it as:
Microsoft.Windows.Controls.DataGrid sellDtg = FindChildLogical<Microsoft.Windows.Controls.DataGrid>(ti, "SellDataGrid");
I hope it gets you where you intend to.
Upvotes: 1