简体   繁体   中英

How can I display distinct value from a Observablecollection?

I have a [Table] Book with columns [Column] Title | Author | Editor | Genre Title | Author | Editor | Genre

I use a Pivot template with the headers Title, Author, Editor, Genre. Example: I have 3 books like this:

1/ Title = "ABC" | Author = "John" | Editor = "Jerry" | Genre = "Novel"

2/ Title = "EFH" | Author = "John" | Editor = "Harry" | Genre = "Mystery"

3/ Title = "HJK" | Author = "Tom" | Editor = "Jerry" | Genre = "Mystery"

What I want is in each Header just show like this :

in Title header: ABC | EFH | HJK ABC | EFH | HJK

in Author header just shows: John | Tom John | Tom

in Editor header just shows: Jerry | Harry Jerry | Harry

in Genre header just shows: Novel | Mystery Novel | Mystery

Code:

 <!--Book-->
        <controls:PivotItem Header="Book">
            <Grid x:Name="ContentPanel1" Margin="12,0,12,0">
                <ListBox x:Name="TitleList" SelectionChanged="TitleList_SelectionChanged" ItemsSource="{Binding Data}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid Width="466" Margin="0, 0, 0, 12">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="10"/>
                                    <ColumnDefinition Width="360"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <Grid Grid.Column="0"></Grid>
                                <StackPanel Grid.Column="1">
                                    <TextBlock FontSize="40"   Text="{Binding BookTitle}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
                                </StackPanel>
                                <Grid Grid.Column="2">
                                    <Button x:Name="Deletebutton" Height="60" Width="60" Click="deleteButton_Click" BorderBrush="{StaticResource TransparentBrush}">
                                     <Image Source="/Assets/delete.dark.png" Visibility="{StaticResource PhoneDarkThemeVisibility}" Margin="-25" HorizontalAlignment="Left"/>
                                    </Button>
                                </Grid>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>

        <!--Author-->
        <controls:PivotItem Header="Author">
            <Grid x:Name="ContentPanel2" Margin="12,0,12,0">
                <ListBox x:Name="AuthorList"  ItemsSource="{Binding Data}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock FontSize="40"   Text="{Binding Author}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>

        <!--Editor-->
        <controls:PivotItem Header="Editor">
            <Grid x:Name="ContentPanel3" Margin="12,0,12,0">
                <ListBox x:Name="EditorList"  ItemsSource="{Binding Data}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock FontSize="40"   Text="{Binding Editor}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>
        <!--Editor-->
        <controls:PivotItem Header="Editor">
            <Grid x:Name="ContentPanel4" Margin="12,0,12,0">
                <ListBox x:Name="BookImporterList"  ItemsSource="{Binding Data}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock FontSize="40"   Text="{Binding Editor}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>
        <!--Genre-->
        <controls:PivotItem Header="Genre">
            <Grid x:Name="ContentPanel5" Margin="12,0,12,0">
                <ListBox x:Name="GenreList"  ItemsSource="{Binding Data}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <TextBlock FontSize="40"   Text="{Binding Genre}" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </controls:PivotItem>
    </controls:Pivot>

In my MainViewModel:

private ObservableCollection<Book> _load = new ObservableCollection<Book>();
public ObservableCollection<Book> Load
{
    get { return _load; }
    set
    {
        _load = value;
        NotifyPropertyChanged("Load");
    }
}
public void LoadData()
{
    var orderedGenre = (from Book b in BookDB.Books select b);
}

This is one of some possible way to get what you want.

In the ViewModel provide one property to store all Books, it is Load property in this case. Then declare new property for every Book's property you want to display. Each of them returning collection of distinct values from corresponding Book property. In the setter of Load property I raise PropertyChanged event for all properties that return values from Load property.

There are two ways I provide here to get distinct values from ObservableCollection of Book, by using Distinct method, or using GroupBy method. But I prefer the first way just because it shorter/simpler in this case.

private ObservableCollection<Book> _load = new ObservableCollection<Book>();
public ObservableCollection<Book> Load
{
    get { return _load; }
    set
    {
        _load = value;
        NotifyPropertyChanged("Load");
        NotifyPropertyChanged("Titles");
        NotifyPropertyChanged("Authors");
    }
}

public ObservableCollection<String> Titles
{
    get { return new ObservableCollection<string>(Load.Select(o => o.Title).Distinct()); }
    //get { return new ObservableCollection<string>(Load.GroupBy(o => o.Title).Select(o => o.Key)); }
}

public ObservableCollection<String> Authors
{
    get { return new ObservableCollection<string>(Load.Select(o => o.Author).Distinct()); }
    //get { return new ObservableCollection<string>(Load.GroupBy(o => o.Title).Select(o => o.Key)); }
}

public void LoadData()
{
    var orderedGenre = (from Book b in BookDB.Books select b);
    Load = new ObservableCollection<Book>(orderedGenre);
}

Then in XAML, bind each ListBox's ItemsSource to corresponding property that have been created in ViewModel :

<controls:PivotItem Header="Book">
    <Grid x:Name="ContentPanel1" Margin="12,0,12,0">
        <ListBox x:Name="TitleList" SelectionChanged="TitleList_SelectionChanged" ItemsSource="{Binding Titles}">
        ....

        ....
<controls:PivotItem Header="Author">
        <Grid x:Name="ContentPanel2" Margin="12,0,12,0">
            <ListBox x:Name="AuthorList"  ItemsSource="{Binding Authors}">
        ....

        ....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM