How to create a list feed
In this tutorial, you will learn how to create an MVUX project that asynchronously requests and displays a collection of items from a service, and enables refreshing the data.
In this tutorial, you will learn how to create an MVUX project and the basic usage of a list-feed (IListFeed<T>), and the FeedView control.
- For our data, we're going to create a service that asynchronously provides a collection of Personentities upon request.
- You'll learn how to use a feed to asynchronously request this data from the service.
- How to display the data on the UI
- How to use the FeedViewcontrol to display the data and automatically respond to the current feed status.
- Use a refresh button to retrieve the latest weather data on-demand.
PeopleApp Sample
You can find the code of this tutorial here.
Create the Model
- Create an MVUX project by following the steps in this tutorial, and name your project PeopleApp. 
- Add a class named PeopleService.cs, and replace its content with the following: - namespace PeopleApp; public partial record Person(string FirstName, string LastName); public interface IPeopleService { ValueTask<IImmutableList<Person>> GetPeopleAsync(CancellationToken ct); } public class PeopleService { public async ValueTask<IImmutableList<Person>> GetPeopleAsync(CancellationToken ct) { await Task.Delay(TimeSpan.FromSeconds(2), ct); var people = new Person[] { new Person(FirstName: "Master", LastName: "Yoda"), new Person(FirstName: "Darth", LastName: "Vader") }; return people.ToImmutableList(); } }- We're using a record for the - Persontype on purpose, as records are designed to be immutable to ensure the purity of objects as well as other features.- The - IListFeed<T>is a feed type tailored for dealing with collections.
- Create a class named PeopleModel.cs replacing its content with the following: - using Uno.Extensions.Reactive; namespace PeopleApp; public partial record PeopleModel(IPeopleService PeopleService) { public IListFeed<Person> People => ListFeed.Async(PeopleService.GetPeopleAsync); }- Note- Feeds ( - IFeed<T>and- IListFeed<T>for collections) are used as a gateway to asynchronously request data from a service and wrap the result or an error if any in metadata to be displayed in the View in accordingly. Learn more about list-feeds here.- Tip- Feeds are stateless and are there for when the data from the service is read-only and we're not planning to enable edits to it. MVUX also provides stateful feeds. For that purpose States ( - IState<T>and- <IListState<T>for collections) come in handy. Refer to this tutorial to learn more about states.
Data-bind the view
PeopleModel exposes a People property which is an IListFeed<T> where T is a Person.
This is similar in concept to an IObservable<IEnumerable<T>>, where an IListFeed<T> represents a sequence of person-collections obtained from the service.
Tip
An IListFeed<T> is awaitable, meaning that to get the value of the feed you would do the following in the model:
IImmutableList<Person> people = await this.People;
To make it possible to data bind to feeds, the MVUX analyzers read the PeopleModel
and generate a ViewModel called PeopleViewModel,
which exposes properties that the View can data bind to.
- Open the file - MainView.xamland add the following namespace to the XAML:- xmlns:mvux="using:Uno.Extensions.Reactive.UI"
- Replace anything inside the - Pagecontents with the following code:- <mvux:FeedView Source="{Binding People}"> <DataTemplate> <ListView ItemsSource="{Binding Data}"> <ListView.Header> <Button Content="Refresh" Command="{Binding Refresh}" /> </ListView.Header> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Spacing="5"> <TextBlock Text="{Binding FirstName}"/> <TextBlock Text="{Binding LastName}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> </DataTemplate> </mvux:FeedView>- Tip- The - FeedViewwraps its source (in this case the- Peoplefeed) in a- FeedViewStateobject, and makes the current value of the feed accessible via its- Dataproperty as well as the- Refreshproperty, which is a command that explicitly triggers reloading the data.
- Press F7 to navigate to open code-view, and in the constructor, after the line that calls - InitializeComponent(), add the following line:- this.DataContext = new PeopleViewModel(new PeopleService());
- Click F5 to run the project. 
- When the app loads you'll notice how the - ProgressTemplateshows (if you've included one), till the data is received from the service (2 seconds). 
- Once the data is available, the - FeedViewswitches to its- ValueTemplate(the first default- DataTemplatein our example), and displays the people list. 
- If you're using Visual-Studio 2022, Right-click the - PeopleAppproject, and navigate to Dependencies. Open up netX.0-windows10.0... → Analyzers. Under Uno.Extensions.Reactive.Generator, expand Uno.Extensions.Reactive.FeedGenerator. Here you'll be able to inspect all files MVUX has generated for you, and learn more about how MVUX runs behind the scenes. - Read inspecting the generated code for more. 
Add search / filtering criteria
Let assume that we want to display only items that match some given criteria.
- Update the file PeopleService.cs, to add a - PersonCriteriaparameter to the- GetPeopleAsyncmethod:- namespace PeopleApp; public partial record PersonCriteria(string? Term, bool IsDarkSideOnly) { public bool Match(Person person) { if (Term is { Length: > 0 } term && !person.FirstName.Contains(term,StringComparison.OrdinalIgnoreCase) && !person.LastName.Contains(term, StringComparison.OrdinalIgnoreCase)) { return false; } if (IsDarkSideOnly && !person.IsDarkSide) { return false; } return true; } } public partial record Person(string FirstName, string LastName, bool IsDarkSide); public interface IPeopleService { ValueTask<IImmutableList<Person>> GetPeopleAsync(PersonCriteria criteria, CancellationToken ct); } public class PeopleService { public async ValueTask<IImmutableList<Person>> GetPeopleAsync(PersonCriteria criteria, CancellationToken ct) { await Task.Delay(TimeSpan.FromSeconds(2), ct); var people = new Person[] { new Person(FirstName: "Master", LastName: "Yoda", IsDarkSide: false), new Person(FirstName: "Darth", LastName: "Vader", IsDarkSide: true) }; return people.Where(criteria.Match).ToImmutableList(); } }
- Update the PeopleModel.cs file with the following: - using Uno.Extensions.Reactive; namespace PeopleApp; public partial record PeopleModel(IPeopleService PeopleService) { public IState<PersonCriteria> Criteria => State.Value(this, () => new PersonCriteria()); public IListFeed<Person> People => Criteria.Select(PeopleService.GetPeopleAsync).AsListFeed(); }- Note- Here we use the - AsListFeedoperator to create the- ListFeed. This converts a- Feed<ImmutableList<T>>to an- IListFeed<T>(Cf. AsListFeed).
- Finally update your view - MainView.xamlto add UI to edit the criteria:- <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel> <TextBox Header="Search term" Text="{Binding Criteria.Term, Mode=TwoWay}" /> <ToggleSwitch Header="Show the dark side only" IsOn="{Binding Criteria.IsDarkSideOnly, Mode=TwoWay}" /> </StackPanel> <mvux:FeedView Source="{Binding People}"> <DataTemplate> <ListView ItemsSource="{Binding Data}"> <ListView.Header> <Button Content="Refresh" Command="{Binding Refresh}" /> </ListView.Header> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Spacing="5"> <TextBlock Text="{Binding FirstName}"/> <TextBlock Text="{Binding LastName}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> </DataTemplate> </mvux:FeedView> </Grid>