views:

43

answers:

1

Hi,

I have quite a tricky problem:

I am using a ListView control with the ItemsSource set to a CollectionViewSource including a PropertyGroupDescription to group the ListView elements. The CollectionViewSource looks like this:

<CollectionViewSource x:Key="ListViewObjects">
   <CollectionViewSource.Source>
      <Binding Path="CurrentListViewData"/>
   </CollectionViewSource.Source>
   <CollectionViewSource.GroupDescriptions>
      <PropertyGroupDescription PropertyName="ObjectType" />
   </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

In the ListView I use customize the group headers like this:

<ListView.GroupStyle>
   <GroupStyle>
      <GroupStyle.ContainerStyle>
         <Style TargetType="{x:Type GroupItem}">
            <Setter Property="Margin" Value="5"/>
            <Setter Property="Template">
               <Setter.Value>
                  <ControlTemplate TargetType="{x:Type GroupItem}">
                     <Expander IsExpanded="True">
                        <Expander.Header>
                           <DockPanel>
                              <TextBlock Text="{Binding Path=Items[0].ObjectType />
                           </DockPanel>
                        </Expander.Header>
                        <Expander.Content>
                           <ItemsPresenter />
                        </Expander.Content>
                     </Expander>
                  </ControlTemplate>
               </Setter.Value>
            </Setter>
         </Style>
      </GroupStyle.ContainerStyle>
   </GroupStyle>
</ListView.GroupStyle>

As you can see the IsExpanded property of the Expander is set to true. This means that whenever the ListView is refreshed, all Expander controls are expanded.

I do however want to save the last state of every Expander. I haven't been able to figure out a way to save a list of Expander states per ObjectType. I was experimenting with a bound HashTable and a Converter, but I failed at providing the ObjectType as a ConverterParameter, because it was always passed as a string. But that may not be the solution anyways.

Can somebody give me a hint or an idea for a solution, please? :)

+1  A: 

You could create a new class with a Dictionary (say, ObjectType as a key to bool values), and give it an indexer:

    Dictionary<ObjectType, bool> expandStates = new Dictionary<ObjectType, bool>();

    public bool this[ObjectType key]
    {
        get
        {
            if (!expandStates.ContainsKey(key)) return false;
            return expandStates[key];
        }
        set
        {
            expandStates[key] = value;
        }
    }

Then, instantiate it in a ResourceDictionary somewhere and bind the IsExpanded to it like this:

<Expander IsExpanded="{Binding Source={StaticResource myExpMgr}, Path=[Items[0].ObjectType]}">

That might well do it: a nice way of getting WPF to call your code and pass a parameter just when you need it. (That WPF lets you put subexpressions in indexers in a binding path was news to me - good though isn't it!)

Kieren Johnstone
I should also add that rather than using NotifyPropertyChanged() you could bind to an object that implements INotifyCollectionChanged (http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx), or use an ObservableCollection. Not sure that it wouldn't cause the same issues though!
Kieren Johnstone