Reputation: 1168
I have a DataGrid, which I bind in the constructor function of my UserControl (after InitializeComponent). I need to access some rows in it, so in the loaded event for the UserControl, I run:
DataGridRow row = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIdx);
However whenever I do that, ItemContainerGenerator.ContainerFromIndex returns null. Seemed like the DataGrid wasn't fully generated yet, so to test/confirm that theory, I threw a button on the screen, and on the click event of the button, I ran that code again, and then sure enough, the row had a value. So, it's confirmed, when the UserControl's loaded event fires, it happens too early and I can't yet call ItemContainerGenerator.ContainerFromIndex for my DataGrid.
What event gets fired after loaded that I could use instead?
Note: I also tried this code that I found, but got the same results:
DataGridRow row = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIdx);
if (row == null)
{
myDataGrid.UpdateLayout();
myDataGrid.ScrollIntoView(myDataGrid.Items[rowIdx]);
row = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIdx);
}
And I also tried doing it in the DataGrid's loaded event but same results.
Thanks!
Upvotes: 5
Views: 7841
Reputation: 1168
Thanks everyone! This ended up doing the trick:
myDataGrid.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
:
:
void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
if (myDataGrid.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
DataGridRow row = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIdx);
if (row == null)
{
myDataGrid.UpdateLayout();
myDataGrid.ScrollIntoView(myDataGrid.Items[rowIdx]);
row = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromIndex(rowIdx);
}
}
}
Upvotes: 4
Reputation: 54532
It looks according to this article that the last event on a new form would be the ContentRendered event.
But it looks like from this article, for the usercontrol the last event would be the Loaded event.
You might try setting a timer with a small delay at the end of your loaded event to run your code in order to get some seperation.
Upvotes: 0
Reputation: 132548
You can run that code at a lower DispatcherPriority than Loaded, such as Input
For example, the DataGrid's Loaded
event would contain something that looks like this:
MyDataGrid.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(delegate() { RunSomeFunction(); } ));
Upvotes: 6