Here's the example I was looking at and I wanted to try that method on it:

The main visual of AddView is a Grid and each of those component, i.e. Plot, Space, Tenant, etc., is FrameworkElement, CardView. Without threading I do it like this:
class AddView : View
{
var plot = new AddPlot();
var space = new AddSpace();
var tenant = new AddTenant();
var head = new AddHead();
var lease = new AddLease();
Grid.SetColumn(space, 1);
Grid.SetColumn(lease, 2);
Grid.SetRowSpan(lease, 2);
Grid.SetRow(tenant, 1);
Grid.SetRow(head, 1);
Grid.SetColumn(head, 1);
grid = new Grid() {
RowDefinitions = {
new RowDefinition(),
new RowDefinition()
},
ColumnDefinitions = {
new ColumnDefinition(),
new ColumnDefinition(),
new ColumnDefinition()
},
Children = { plot, space, lease, tenant, head }
};
AddVisualChild(grid);
}
}
My View class is:
abstract class View : FrameworkElement
{
public virtual string Icon { get; }
public abstract FrameworkElement container { get; }
protected override Size MeasureOverride(Size availableSize) {
container.Measure(availableSize);
return container.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize) {
container.Arrange(new Rect(container.DesiredSize));
return finalSize;
}
protected override Visual GetVisualChild(int index) => container;
protected override int VisualChildrenCount => 1;
}
and the CardView class is:
abstract class CardView : View
{
public abstract string Header { get; }
public override FrameworkElement container => card;
Card card;
public CardView() {
card = new Card() {
IsRound = true,
Header = Header
};
AddVisualChild(card);
KeyboardNavigation.SetTabNavigation(this, KeyboardNavigationMode.Cycle);
}
protected void setContent(FrameworkElement element) => card.Content = element;
}
Here you can see how I load content in CardView. In my AddView, I've tried with the following way to give each CardView a separate thread:
class AddView : View
{
override public string Icon => Icons.Add;
public override FrameworkElement container => grid;
Grid grid;
public AddView() {
grid = new Grid() {
RowDefinitions = {
new RowDefinition(),
new RowDefinition()
},
ColumnDefinitions = {
new ColumnDefinition(),
new ColumnDefinition(),
new ColumnDefinition()
}
};
AddVisualChild(grid);
var plotThread = new Thread(() => {
var plot = new AddPlot();
Dispatcher.Invoke(() => grid.Children.Add(plot));
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true };
plotThread.SetApartmentState(ApartmentState.STA);
plotThread.Start();
var spaceThread = new Thread(() => {
var space = new AddSpace();
Grid.SetColumn(space, 1);
Dispatcher.Invoke(() => grid.Children.Add(space));
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true }; ;
spaceThread.SetApartmentState(ApartmentState.STA);
spaceThread.Start();
var tenantThread = new Thread(() => {
var tenant = new AddTenant();
Grid.SetRow(tenant, 1);
Dispatcher.Invoke(() => grid.Children.Add(tenant));
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true }; ;
tenantThread.SetApartmentState(ApartmentState.STA);
tenantThread.Start();
var headThread = new Thread(() => {
var head = new AddHead();
Grid.SetRow(head, 1);
Grid.SetRow(head, 1);
Dispatcher.Invoke(() => grid.Children.Add(head));
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true }; ;
headThread.SetApartmentState(ApartmentState.STA);
headThread.Start();
var leaseThread = new Thread(() => {
var lease = new AddLease();
Grid.SetColumn(lease, 2);
Grid.SetRowSpan(lease, 2);
Dispatcher.Invoke(() => grid.Children.Add(lease));
System.Windows.Threading.Dispatcher.Run();
}) { IsBackground = true }; ;
leaseThread.SetApartmentState(ApartmentState.STA);
leaseThread.Start();
}
}
and that doesn't work! I get System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'