Nullqwerty
Nullqwerty

Reputation: 1168

What Event Happens After Loaded For A WPF UserControl?

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

Answers (3)

Nullqwerty
Nullqwerty

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

Mark Hall
Mark Hall

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

Rachel
Rachel

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

Related Questions