2009-05-22 2 views
8

иногда WPF слишком сложна для меня. У меня есть «Window1», держащий коллекцию «Групп». «Группа» - это класс с коллекцией «Человек». В конце концов, это должен быть список контактов. То, что я просто хочу сделать, - показать группы со своим человеком в ListBox, где групповое имя групп списка равно Именному свойству моего класса «Группы».WPF: коллекция Bind с коллекцией в ListBox с группами

Я попытался использовать CollectionViewSource, привязанный к «Коллекции». Группы отображаются правильно, но элементы списка равны именам групп. Таким образом, каждая группа имеет только один элемент: название своей группы.

Многие примеры здесь показывают группировку предметов только с одной коллекцией. Я могу установить имя группы как «Свойство». Но тогда я не могу сосчитать (и это действительно необходимо): - сколько человек в каждой группе - сколько из этих лиц имеет статус «Онлайн».

Я использую linq в классе «Group», чтобы считать это. Спасибо за любые советы, которые помогут мне начать работу.

ответ

21

Ну, я не уверен, если это то, что вы хотите достичь, но вот способ, который вы можете попробовать:

Предполагая, что классы, как эти:

public class Group 
{ 
    public string Name { get; set; } 
    public List<Contact> Contacts { get; set; } 
} 

public class Contact 
{ 
    public string Name { get; set; } 
    public bool IsOnline { get; set; } 
} 

Вы можно установить ListBox.ItemTemplate как другой ListBox связываются Контакты собственности, как:

<CollectionViewSource x:Key="groups" Source="{Binding}" > 
    <CollectionViewSource.GroupDescriptions> 
     <PropertyGroupDescription PropertyName="Name" /> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 

<DataTemplate x:Key="groupTemplate" DataType="Group"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="{Binding Name}" /> 
    </StackPanel> 
</DataTemplate> 

<ListBox ItemsSource="{Binding Source={StaticResource groups}}"> 
    <ListBox.GroupStyle> 
     <GroupStyle HeaderTemplate="{StaticResource groupTemplate}" /> 
    </ListBox.GroupStyle> 
    <ListBox.ItemTemplate> 
     <DataTemplate DataType="Contact"> 
      <ListBox ItemsSource="{Binding Contacts}"> 
       <ListBox.ItemTemplate> 
        <DataTemplate DataType="Contact"> 
         <TextBlock Text="{Binding Name}" /> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Вы должны стиль внутреннего LISTB бык немного.

Редактировать: Еще одно решение, используя TreeView

<DataTemplate DataType="Contact"> 
    <TextBlock Text="{Binding Name}" /> 
</DataTemplate> 

<TreeView ItemsSource="{Binding Source={StaticResource groups}}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding Contacts}"> 
      <TextBlock Text="{Binding Name}" /> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 
+0

Это тихо помогает и соответствует моему старому решению, где у меня есть Expander для каждой группы и ListBox для контактов. Проблема здесь в том, что вы можете выбрать человека в списке, но я предположил, что вы можете сделать это с одним. Я пытаюсь скопировать пользовательский интерфейс списка контактов Windows Live Messenger 2009. Я думаю, что они использовали только один ListBox и Expander в качестве ControlTemplate для группы. Но я также предполагаю, что они определили группу как свойство. Но я действительно не знаю, как они могут рассчитывать онлайн-людей. Кстати, вы правы со своими классами. – 2009-05-22 08:01:42

+0

Почему вы не используете элемент управления TreeView для отображения иерархических данных? – idursun

+0

Вы абсолютно правы! Я думаю, это решило бы мою проблему наверняка. У меня нет ответа на вопрос «почему». Я не использовал элемент управления TreeView. Но это было бы лучше для моей проблемы. Благодаря! – 2009-05-22 09:01:32

8

Если у вас есть копия Programming WPF, прыгайте на странице 221. Если я не буду обобщать (в моем неумелом виде пути)

Сначала вам не нужно вручную группировать объекты Person.

Если каждый объект Person имеет свойство Group,

People people = // retrieve the List<Person> somehow 
ICollectionView view = CollectionViewSource.GetDefaultView(people); 
view.GroupDescriptions.Add(new PropertyGroupDescription("Group")); 

Все элементы управления, которые являются производными от ItemsControl может отображать сгруппированных элементов, так

// the XAML 
<ListBox ... ItemsSource={Binding}> 
    <ListBox.GroupStyle> 
    <x:Static Member="GroupStyle.Default" /> 
    </ListBox.GroupStyle> 
</ListBox> 

Вы можете также определить пользовательские GroupStyle и указать GroupStyle .HeaderTemplate, чтобы определить новый DataTemplate, который показывает пользовательские атрибуты, такие как «some PropertyValue (Count)» - привязать один TextBlock к {Binding SomeProperty}, а другой - к {Binding ItemCount}

НТН

+0

Спасибо, первый. У моего объекта Person еще нет свойства группы. Я бы хотел этого избежать. Я не понимал, как я могу обработать счет (только логика, факт с TextBlock ясен). Вот какой-то код, если он вам поможет. перечисление OnlineStatus {ONLINE, OFFLINE} класс Person { // Заголовок каждой группы должны рассчитывать // сколько человек существует с OnlineStatus "Online". Публичный статус OnlineStatus {get; задавать; } } класс Группа { открытый список Персоналии = новый Список (); } класс Window1 { общественный список Группы = новый Список ; } – 2009-05-22 07:10:15

+0

+1, '{Binding ItemCount}' был ответом, в котором я нуждался! СПАСИБО! – Dom

Смежные вопросы