0
votes

I have a WPF TabControl with two TabItems. Each TabItem contains a ListBox with a separate ObservableCollection as its ItemsSource. Each ListBox has a different ItemTemplate.

No matter which TabItem I set to be selected at startup, that tab will be displayed fine, but when I click on the other tab the application crashes with an 'Exception has been thrown by the target of an invocation' error pointing toward the DataTemplate for the tab I'm switching to.

If I remove the ItemTemplate from the ListBox on the tab I'm trying to switch to (and use DisplayMemberPath) everything works fine.

However, if I use a DataTemplate, whether it be inline or as a StaticResource or DynamicResource, it causes the crash on tab switching.

Any ideas? Pseudo-code follows:


<Window x:Class="Example.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:objects="clr-namespace:Example.CoreObjects"
    xmlns:controls="clr-namespace:Example.Controls"
    >
<Window.Resources>
    <DataTemplate x:Key="ItemTemplateOne">
        <controls:CustomControlOne />
    </DataTemplate>
    <DataTemplate x:Key="ItemTemplateTwo">
        <controls:CustomControlTwo />
    </DataTemplate>
</Window.Resources>
<Grid>
    <TabControl Name="tabControl1">
        <TabItem Header="TabOne">
            <Grid>
                <ScrollViewer>
                    <ListBox Name="ListBoxOne" 
                             ItemsSource="{Binding}"
                             ItemTemplate="{StaticResource ItemTemplateOne}"
                             >
                        <ListBox.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel /> 
                            </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
                    </ListBox>
                </ScrollViewer>
            </Grid>
        </TabItem>
        <TabItem Header="TabTwo">
            <Grid>
                <ScrollViewer>
                    <ListBox Name="ListBoxTwo" 
                             ItemsSource="{Binding}"
                             ItemTemplate="{StaticResource ItemTemplateTwo}"
                             >
                        <ListBox.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel />
                            </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
                    </ListBox>
                </ScrollViewer>
            </Grid>
        </TabItem>
    </TabControl>
</Grid>

public Window1() { InitializeComponent();

ListBoxOne.DataContext = ObservableCollectionOne;
CollectionViewOne = CollectionViewSource.GetDefaultView(ObservableCollectionOne);
CollectionViewOne.SortDescriptions.Add(new SortDescription("SortProperty", ListSortDirection.Descending));

ListBoxTwo.DataContext = ObservableCollectionTwo;
CollectionViewTwo = CollectionViewSource.GetDefaultView(ObservableCollectionTwo);
CollectionViewTwo.SortDescriptions.Add(new SortDescription("SortProperty", ListSortDirection.Descending));

}

2

2 Answers

1
votes

No matter which TabItem I set to be selected at startup, that tab will be displayed fine, but when I click on the other tab the application crashes with an 'Exception has been thrown by the target of an invocation' error pointing toward the DataTemplate for the tab I'm switching to.

Enable first-chance exceptions, so you can find out the actual exception instead of the wrapped outer exception - what's going wrong will be much clearer.

0
votes

I think the problem is that both ListBox's ItemSource="{Binding}". I think this says to bind to the Window's DataContext, but in code you set the separately.

Try declaring a CollectionViewSource (or two if you want different sorts between ListBoxes) in your Window.Resources. Set your Observablecollection as the source of of the CollectionViewSource.

Then in your ListBoxes, do binding to the CollectionView source.

If this doesn't work, you could try putting each ListBox and its associated data resources into separate UserControls.