1

I have a TabConrol that when a user does certain things, a new TabItem is programmatically added. In this tab there is a Frame that will contain the desired Page.XAML. This is all working perfectly like this;

private void addNewTab()
{
   TabItem tab = new TabItem();
   Grid g = new Grid();
   Frame f = newFrame();
   g.Children.Add(f);
   tab.Content = g;
   MyTabControl.Items.Add(tab);
   MyTabControl.SelectedItem = tab;
}

private Frame newFrame()
{
   Frame f = new Frame();
   //Full logic for Frame removed
   f.Navigate(new MyPage());
   return f;
}

Issues is sometimes the loading of the new Frame can take sometime. So I wanted to do this async. So while it loads there could be a loading animation. I figured that this would work;

private async void addNewTab()
{
   TabItem tab = new TabItem();
   Grid g = new Grid();

   var test = Task<Frame>.Factory.StartNew(() => newFrame(selectTab, value));
   await test;
   f = test.Result;

   g.Children.Add(f);
   tab.Content = g;
   MyTabControl.Items.Add(tab);
   MyTabControl.SelectedItem = tab;
}

private Frame newFrame()
{
   Frame f = new Frame();
   //Full logic for Frame removed
   f.Navigate(new MyPage());
   return f;
}

Problem is that it returns the follow error on Frame f = new Frame(); in newFrame() at run;

An exception of type 'System.InvalidOperationException' occurred in PresentationCore.dll but was not handled in user code

Additional information: The calling thread must be STA, because many UI components require this.

Starting to think I am trying to solve this the wrong way. What is the best way to handle this?

1

1 Answer 1

6

Building any reasonable UI is an extremely fast operation. However, determining the data to display in that UI can take any amount of time. So I assume that's what's actually slow.

You can't build the actual UI components on a background thread; that's what the exception tells you.

But you can build the data on the background thread and then later load it into the UI:

private async Task addNewTabAsync()
{
  TabItem tab = new TabItem();
  Grid g = new Grid();

  var data = await Task.Run(() => getData(value));
  Frame f = new Frame();
  // Fill out frame with data.
  f.Navigate(new MyPage());

  g.Children.Add(f);
  tab.Content = g;
  MyTabControl.Items.Add(tab);
  MyTabControl.SelectedItem = tab;
}

Note that I changed async void to async Task (and added the Async suffix), and changed StartNew to Run to follow best practices.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.