views:

382

answers:

2

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));

}

A: 

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.

Geoff Cox
+1  A: 

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.

Paul Betts
I dug into the stack trace and discovered my foolish error. The two DataTemplates each used custom controls with very similar properties. I had copied and pasted DependencyProperty code from custom control one to custom control two, but forgot to change the type it was registered by.
Ben