question

IDGO-6443 avatar image
0 Votes"
IDGO-6443 asked ·

UWP - MVVM Listbox with ObservableCollection Need Filter and Update UI.

UWP - MVVM Listbox with ObservableCollection Need Filter and Update UI.

In Simple Words : Need MVVM Listbox Filter Collection...

Someting Similar to this in UWP :
https://markheath.net/post/list-filtering-in-wpf-with-m-v-vm

list-filtering-in-wpf-with-m-v-vm


windows-uwpwindows-uwp-xamlwindows-uwp-runtime
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

PeterFleischer-3316 avatar image
1 Vote"
PeterFleischer-3316 answered ·

Hi,
here is another approach to load data asynchnously without blocking UI.

XAML:

 <Page
     x:Class="App1.Page14"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="using:App14"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   <Page.DataContext>
     <local:ViewModel/>
   </Page.DataContext>
   <StackPanel>
     <TextBox Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
     <ListBox ItemsSource="{Binding View}" DisplayMemberPath="Info" Height="400"/>
   </StackPanel>
 </Page>

and classes:

25106-x.png

It's impossible to include in this buggy forum software code, see attached txt: 25142-x.txt

Result:

25035-x.gif



x.gif (109.8 KiB)
x.txt (2.5 KiB)
x.png (67.1 KiB)
· 1 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks Peter...this should help when collection is huge....If any challenges found will Create a New Thread.

0 Votes 0 · ·
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi,
try following demo:

 <Page
     x:Class="UWP10App1VB.Page20"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="using:UWP10App1VB.App20"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   <Page.DataContext>
     <local:ViewModel/>
   </Page.DataContext>
   <StackPanel>
     <TextBox Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
     <ListBox ItemsSource="{Binding View}" DisplayMemberPath="Info" Height="400"/>
   </StackPanel>
 </Page>

and classes:

 Namespace App20
   Public Class ViewModel
     Implements INotifyPropertyChanged
    
     Private _filter As String
     Public Property Filter As String
       Get
         Return Me._filter
       End Get
       Set(value As String)
         Me._filter = value
         OnPropertyChanged(NameOf(View))
       End Set
     End Property
     Private col As ObservableCollection(Of Data)
    
     Public ReadOnly Property View As IEnumerable(Of Data)
       Get
         If col Is Nothing Then col = LoadData()
         Return col.Where((Function(d As Data)
                             Return String.IsNullOrEmpty(Me._filter) OrElse d.Info.Contains(Me._filter)
                           End Function))
       End Get
     End Property
    
     Private Function LoadData() As ObservableCollection(Of Data)
       Dim col As New ObservableCollection(Of Data)
       For i = 1 To 200
         col.Add(New Data With {.ID = i, .Info = $"Row {i}"})
       Next
       Return col
     End Function
    
     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
     Friend Sub OnPropertyChanged(<CallerMemberName> Optional propName As String = "")
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
     End Sub
    
   End Class
    
   Public Class Data
     Public Property ID As Integer
     Public Property Info As String
   End Class
    
 End Namespace

Result:

24922-x.gif



x.gif (49.8 KiB)
· 2 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hey Peter,

I have 1 Problem in View Property

   public IEnumerable<Data> View
         {
             get
             {
                 if (col == null)
                 {
                     col = LoadData();
                 }
                 return col.Where(((Data d) =>
                 {
                     return string.IsNullOrEmpty(this._filter) || d.Info.Contains(this._filter);
                 }));
             }
         }

1. I can't load Data in Get , I need to load data from external code or set data.
2. return col.Where(((Data d) =>
{
return string.IsNullOrEmpty(this._filter) || d.Info.Contains(this._filter);
}));
``This Line Might Cause Performance Issue. Because it loops through on load and also on Filter Change Text. Can we stop looping on load and Fine looping if filter text change.





0 Votes 0 · ·

Hello @IDGO-6443 , Regarding the first question, you can call the LoadData method when the ViewModel class is initialized. Regarding the second question, maybe you can add a timer to count when the user stops typing. If a certain time (such as 0.5s) is reached, perform a search and reset the timer, which can avoid too frequent data queries.

0 Votes 0 · ·