2010-04-07 5 views
2

J'ai une collection de ViewModels et je veux lier un ListBox à eux. En faisant une enquête j'ai trouvé this.Lier la zone de liste dans WPF avec le groupement

Alors mes ViewModel ressembler à ceci (code pseudo)

interface IItemViewModel 
{ 
string DisplayName { get; } 
} 

class AViewModel : IItemViewModel 
{ 
string DisplayName { return "foo"; } 
} 

class BViewModel : IItemViewModel 
{ 
string DisplayName { return "foo"; } 
} 

class ParentViewModel 
{ 
IEnumerable<IItemViewModel> Items 
{ 
    get 
    { 
    return new IItemViewModel[] { 
    new AItemViewModel(), 
    new BItemViewModel() 
    } 
    } 
} 
} 

class GroupViewModel 
{ 
static readonly GroupViewModel GroupA = new GroupViewModel(0); 
static readonly GroupViewModel GroupB = new GroupViewModel(1); 

int GroupIndex; 
GroupViewModel(int groupIndex) 
{ 
    this.GroupIndex = groupIndex; 
} 

string DisplayName 
{ 
    get { return "This is group " + GroupIndex.ToString(); } 
} 
} 

class ItemGroupTypeConverter : IValueConverter 
{ 
object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    if (value is AItemViewModel) 
    return GroupViewModel.GroupA; 
    else 
    return GroupViewModel.GroupB; 
} 
} 

Et ce XAML

<UserControl.Resources> 
<vm:ItemsGroupTypeConverter x:Key="ItemsGroupTypeConverter "/> 
<CollectionViewSource x:Key="GroupedItems" Source="{Binding Items}"> 
    <CollectionViewSource.GroupDescriptions> 
    <PropertyGroupDescription Converter="{StaticResource ItemsGroupTypeConverter }"/> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 
</UserControl.Resources> 
<ListBox ItemsSource="{Binding Source={StaticResource GroupedItems}}"> 
<ListBox.GroupStyle> 
    <GroupStyle> 
    <GroupStyle.HeaderTemplate> 
    <DataTemplate> 
    <TextBlock Text="{Binding DisplayName}" FontWeight="bold" /> 
    </DataTemplate> 
    </GroupStyle.HeaderTemplate> 
    </GroupStyle>    
</ListBox.GroupStyle> 
<ListBox.ItemTemplate> 
    <DataTemplate> 
    <TextBlock Text="{Binding DisplayName}" /> 
    </DataTemplate> 
</ListBox.ItemTemplate> 
</ListBox> 

Cela fonctionne en quelque sorte, exepté du fait que la liaison de HeaderTemplate ne fonctionne pas. De toute façon je préférerais omettre le TypeConverter et le CollectionViewSource. N'existe-t-il pas un moyen d'utiliser une propriété de ViewModel pour le regroupement?

Je sais que dans cet exemple de scénario, il serait facile de remplacer le GroupViewModel par une chaîne pour que cela fonctionne, mais ce n'est pas une option. Alors, comment puis-je lier HeaderTemplate au GroupViewModel?

Répondre

10

Ok, je l'ai finalement résolu moi-même. Tout d'abord, le TypeConverter n'est pas nécessaire car la PropertyGroupDescription peut être liée à un PropertyName. J'ai donc ajouté un « groupe » Propriété à IItemViewModel Modifiés XAML comme suit:

<UserControl.Resources> 
<CollectionViewSource x:Key="GroupedItems" Source="{Binding Items}"> 
    <CollectionViewSource.GroupDescriptions> 
    <PropertyGroupDescription PropertyName="Group"/> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 
</UserControl.Resources> 

De plus DataContext du HeaderTemplate est un CollectionViewGroupInternal et la liaison doit ressembler à ceci:

<DataTemplate> 
<TextBlock Text="{Binding Name.DisplayName}" FontWeight="bold" /> 
</DataTemplate> 

Ici CollectionViewGroupInternal.Name résout le GroupViewModel réel.

+1

pourquoi avez-vous utilisé Name.DisplayName dans la section de liaison de texte de votre bloc de texte? Où avez-vous trouvé l'objet "Nom"? – Miles

+1

Le nom est un paramètre de CollectionViewGroupInternal –

Questions connexes