Databinding to ObservableCollection in a different UserControl - how to preserve current selections?

Posted by Dave on Stack Overflow See other posts from Stack Overflow or by Dave
Published on 2010-03-19T20:38:49Z Indexed on 2010/03/29 16:43 UTC
Read the original article Hit count: 481

Scope of question expanded on 2010-03-25

I ended up figuring out my problem, but here's a new problem that came up as a result of solving the original question, because I want to be able to award the bounty to someone!!!

Once I figured out my problem, I soon found out that when the ObservableCollection updates, the databound ComboBox has its contents repopulated, but most of the selections have been blanked out.

I assume that in this case, MVVM is going to make it difficult for me to remember the last selected item. I have an idea, but it seems a little nasty. I'll award the bounty to whomever comes up with a nice solution for this!

Question re-written on 2010-03-24

I have two UserControls, where one is a dialog that has a TabControl, and the other is one that appears within said TabControl. I'll just call them CandyDialog and CandyNameViewer for simplicity's sake. There's also a data management class called Tracker that manages information storage, which for all intents and purposes just exposes a public property that is an ObservableCollection.

I display the CandyNameViewer in CandyDialog via code behind, like this:

private void CandyDialog_Loaded( object sender, RoutedEventArgs e)
{
  _candyviewer = new CandyViewer();
  _candyviewer.DataContext = _tracker;
  candy_tab.Content = _candyviewer;
}

The CandyViewer's XAML looks like this (edited for kaxaml):

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <DataTemplate x:Key="CandyItemTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="120"></ColumnDefinition>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{Binding CandyName}" Margin="3"></TextBox>
                <!-- just binding to DataContext ends up using InventoryItem as parent, so we need to get to the UserControl -->
                <ComboBox Grid.Column="1" SelectedItem="{Binding SelectedCandy, Mode=TwoWay}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CandyNames}" Margin="3"></ComboBox>
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <Grid>
        <ListBox DockPanel.Dock="Top" ItemsSource="{Binding CandyBoxContents, Mode=TwoWay}" ItemTemplate="{StaticResource CandyItemTemplate}" />
    </Grid>
</Page>

Now everything works fine when the controls are loaded. As long as CandyNames is populated first, and then the consumer UserControl is displayed, all of the names are there. I obviously don't get any errors in the Output Window or anything like that.

The issue I have is that when the ObservableCollection is modified from the model, those changes are not reflected in the consumer UserControl! I've never had this problem before; all of my previous uses of ObservableCollection updated fine, although in those cases I wasn't databinding across assemblies. Although I am currently only adding and removing candy names to/from the ObservableCollection, at a later date I will likely also allow renaming from the model side.

Is there something I did wrong? Is there a good way to actually debug this? Reed Copsey indicates here that inter-UserControl databinding is possible. Unfortunately, my favorite Bea Stollnitz article on WPF databinding debugging doesn't suggest anything that I could use for this particular problem.

© Stack Overflow or respective owner

Related posts about wpf

Related posts about databinding