Scrolling a ListView CollectionViewSource to a group of items based on a search textbox's text in C#

badshar

New member
Aug 27, 2014
26
0
0
The following is my XAML code:

<Page.Resources>
<DataTemplate x:Key="GroupTemplate">
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1">
<TextBlock x:Name="SongTitle" Text="{Binding Title}"
Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock x:Name="ArtistName" Text="{Binding Album}"
Style="{ThemeResource ListViewItemContentTextBlockStyle}"/>
</StackPanel>
</Grid>
</DataTemplate>

<CollectionViewSource x:Name="MusicSource" IsSourceGrouped="true" />

<DataTemplate x:Key="headerTemplate">
<StackPanel HorizontalAlignment="Stretch" Width="{Binding ActualWidth, ElementName=contentList}">
<TextBlock Text="{Binding Key}" />
</StackPanel>
</DataTemplate>
</Page.Resources>

<Grid>
<SemanticZoom>
<SemanticZoom.ZoomedInView>
<ListView
x:Name="contentList"
SelectionMode="Multiple"
ItemsSource="{Binding Source={StaticResource MusicSource}}"
ItemTemplate="{StaticResource GroupTemplate}">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True" HeaderTemplate="{StaticResource headerTemplate}"/>
</ListView.GroupStyle>
</ListView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
<Border
x:Name="SearchBorder"
Background="White">
<TextBox
x:Name="Search" TextChanged="TextBox_TextChanged" />
</Border>
</Grid>

The following is the C# code behind it:

// imports

namespace Test
{
public sealed partial class Player : Page
{
ObservableCollection<Music> source = new ObservableCollection<Music>();
List<AlphaKeyGroup<Music>> itemSource;

public Player()
{
this.InitializeComponent();
this.SetItemSource();
}

private async Task getMusic(IStorageFolder folder)
{
var folders = await folder.GetFoldersAsync();
if (folders != null)
foreach (var fol in folders)
await getMusic(fol);

var files = await folder.GetFilesAsync();
foreach (var file in files)
{
MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
this.source.Add(new Music(musicProperties.Artist, musicProperties.Title, musicProperties.Album));
}
itemSource = AlphaKeyGroup<Music>.CreateGroups(source, CultureInfo.CurrentUICulture, s => s.Artist, true);
this.MusicSource.Source = itemSource;
}

public async void SetItemSource()
{
await getMusic(Windows.Storage.KnownFolders.MusicLibrary);
}

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{

}
}
}

As the user types in the textbox, the listview should automatically scroll to the matching group.

The groups are based on Artist, so it's like:

Michael Jackson
- Song 1
- Song 2

Eminem
- Song 1
- Song 2

So if I type "Em", the listview should immediately scroll down to the second group, since that artist "Eminem" comes closest to "Em".

Is this possible?

I am using the AlphaKeyGroup class.
 
The ListView has a method ScrollIntoView() which allows you to scroll to a specific item within the list. You can set the second parameter to "Leading", mening that the item shall be scrolled to the top of the list. However, I *think* this only works for the items (tracks in your case) and not for the groups. You could try it with the groups, but if it does not work, try to scroll the first track of the group into view. Hope this helps.
 
Yes, this is possible. First, you need a collection of all of the "headers" of each group. Next, when the text changes, you need to search for the first match to what is in the search box within this collection of group headers. Lastly, get the matching group and use the ScrollIntoView() function of the ListView to scroll to the first member of the matching group.
 

Members online

Forum statistics

Threads
335,544
Messages
2,258,548
Members
428,739
Latest member
Stayready216