5 Simple Steps to Design a News Feed App with .NET MAUI ListView 

Jollen Moyani - Aug 8 - - Dev Community

TL;DR: Learn to design a news feed app using Syncfusion .NET MAUI ListView. Follow five steps: create a data model, populate the ViewModel, bind data to ListView, set up item templates, and define UI layout. Enhance your app with adaptable layouts and interactive elements .

A news feed app serves as a comprehensive platform for consuming news and staying updated on topics of interest.

Syncfusion .NET MAUI ListView ( SfListView ) is a versatile control used to present lists of data virtually in a vertical or horizontal orientation with different layouts. It supports essential features such as selection, template selectors, horizontal and vertical orientation, load more, autofitting items, sorting, grouping, and filtering with optimization for working with large amounts of data.

In this blog, we’ll see how to create a news feed app using the Syncfusion .NET MAUI ListView control.

Note: Before proceeding, refer to the getting started with .NET MAUI ListView documentation.

Step 1: Creating a data model

Create a simple data Model class to hold the data values, such as news title, description, and image. Use this data model to create a simple data source to bind the .NET MAUI ListView control.

Refer to the following code example.

public class Model : INotifyPropertyChanged
{
    private string title;
    private string description;
    private bool isLiked;
    private string imageName;
    private string views;
    private string dateTime;
    public string Title
    {
        get => title;
        set
        {
            title = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title)));
        }
    }
    public string Description
    {
        get => description;
        set
        {
            description = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Description)));
        }
    }
    public bool IsLiked
    {
        get => isLiked;
        set
        {
            isLiked = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLiked)));
        }
    }
    public string ImageName
    {
        get => imageName;
        set
        {
            imageName = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ImageName)));
        }
    }
    public string Views
    {
        get => views;
        set
        {
            views = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Views)));
        }
    }
    public string NewsDate
    {
        get => dateTime;
        set
        {
            dateTime = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DateTime)));
        }
    }
    public event PropertyChangedEventHandler? PropertyChanged;
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Populate the model collection in the ViewModel

Let’s create a ViewModel class and populate the News collection property with the required data objects for the .NET MAUI ListView control.

Refer to the following code example.

public class ViewModel
{
    private ObservableCollection<Model> news;
    public ViewModel() 
    {
        this.news = new ObservableCollection<Model>();
        LoadData();
    }
    public ObservableCollection<Model> News
    {
        get => news;
        set
        {
            news = value;
        }
    }
    private void LoadData()
    {

        news.Add(new Model { Title = "Breaking News: MAUI Released!", Description = "Microsoft has officially released .NET MAUI, the next-gen cross-platform framework. Developers can now build apps for Android, iOS, and Windows with a single codebase.",ImageName="maui.png", IsLiked = false });
        news.Add(new Model { Title = "Tech Innovation Summit 2024", Description = "Join us at the Tech Innovation Summit 2024 where industry leaders will discuss the latest advancements in artificial intelligence, blockchain, and more.", ImageName="techinnovation.png", IsLiked = false });
      . . . .
      . . . .
      . . . .
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Set the binding context

Now, set the ViewModel instance as the BindingContext of your page to bind properties of the ViewModel to the .NET MAUI LsitView (SfListView) control.

<ContentPage.BindingContext>
    <local:ViewModel x:Name="vm"/>
</ContentPage.BindingContext>
Enter fullscreen mode Exit fullscreen mode

Step 4: Binding data collection to .NET MAUI ListView

Then, bind the News collection to the ItemsSource property of the SfListView and set the AutoFitMode property to DynamicHeight or Height to set the item height based on the content.

<listView:SfListView x:Name="listView"
                 AutoFitMode="DynamicHeight"
                 ItemsSource="{Binding News}">
Enter fullscreen mode Exit fullscreen mode

Step 5: Defining the item template

Then, define the news feed UI using the .NET MAUI ListView’s ItemTemplate property on the XAML page.

Refer to the following code example.

<listView:SfListView x:Name="listView" AutoFitMode="DynamicHeight" ItemsSource="{Binding News}" SelectionMode="None">
  <listView:SfListView.ItemTemplate>
    <DataTemplate x:DataType="local:Model">
      <Border Stroke="#CAC4D0" Margin="8,8,8,4">
        <Border.StrokeShape>
           <RoundRectangle CornerRadius="12" />
        </Border.StrokeShape>
        <Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto" Margin="8">
          <Frame Grid.Row="0" IsClippedToBounds="True" HasShadow="False" BorderColor="Transparent" Padding="0" CornerRadius="{OnPlatform Android=4,Default=5,MacCatalyst=6}" HeightRequest="148">
            <ffimageloading:CachedImage Source="{Binding ImageName}" Aspect="Fill" HeightRequest="148"/>
          </Frame>
          <Label Grid.Row="1" Margin="0,10,0,5" Text="{Binding Title}" FontSize="14" FontAttributes="Bold"/>
          <Grid Grid.Row="2" ColumnDefinitions="Auto,14,*" Margin="0,5,0,5">
             <Label Text="{Binding NewsDate}" FontSize="11"/>
             <Label Grid.Column="1" HeightRequest="14" FontFamily="ListViewFont" Text="" TextColor="#49454F" FontSize="14" VerticalOptions="Center"/>
             <Label Grid.Column="2" Text="{Binding Views}" FontSize="11" Margin="5,0,0,0"/>
          </Grid>
          <Label Grid.Row="3" Margin="0,5,0,0" Text="{Binding Description}" FontSize="14"/>
          <Grid Grid.Row="4" ColumnDefinitions="*,*,80" RowDefinitions="24" Margin="0,10,0,0">
           <Frame Grid.Column="0" IsClippedToBounds="True" HasShadow="False" BorderColor="Transparent" Padding="0" CornerRadius="20" WidthRequest="72" HeightRequest="24" HorizontalOptions="Start">
              <Frame.GestureRecognizers>
                <TapGestureRecognizer Command="{Binding Path=BindingContext.LikeActionCommand, Source={x:Reference listView}}" CommandParameter="{Binding .}"/>
              </Frame.GestureRecognizers>
              <Label WidthRequest="72" HeightRequest="24" Text="{Binding IsLiked, Converter={StaticResource iconConverter}}" FontFamily="ListViewFont" FontSize="13" Background="#EEE8F4" TextColor="#49454F" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
           </Frame>
           <Frame Grid.Column="1" IsClippedToBounds="True" HasShadow="False" BorderColor="Transparent" Padding="0" CornerRadius="20" WidthRequest="72" HeightRequest="24" HorizontalOptions="End">
             <Label WidthRequest="72" HeightRequest="24" Text="" FontFamily="ListViewFont" FontSize="13" Background="#EEE8F4" TextColor="#49454F" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
           </Frame>
           <Frame Grid.Column="2" IsClippedToBounds="True" HasShadow="False" BorderColor="Transparent" Padding="0" CornerRadius="20" WidthRequest="72" HeightRequest="24" HorizontalOptions="End">
             <Label WidthRequest="72" HeightRequest="24" Text="" FontFamily="ListViewFont" FontSize="13" Background="#EEE8F4" TextColor="#49454F" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/>
           </Frame>
        </Grid>
       </Grid>
     </Border>
   </DataTemplate>
  </listView:SfListView.ItemTemplate>

</listView:SfListView>
Enter fullscreen mode Exit fullscreen mode

In the above code example, the ItemTemplate within the ListView specifies how each item should be displayed. It uses a DataTemplate to define the layout and appearance of each news item. The template includes a border with rounded corners and a grid layout to organize the content neatly.

In our demo, we will display an image at the top of each item using the ffimageloading technique, which ensures efficient loading and caching of images. Below the image, the news title will be displayed in bold, followed by the news date and the number of views, which are arranged in a grid layout for clarity.

The news item’s description is displayed next, providing a brief overview of the content. At the bottom of each item, there are action buttons for liking, sharing, and other interactions. These buttons are designed with gesture recognizers to handle user interactions, making the ListView not only informative but also interactive.

Refer to the following output image.

Creating a news feed app using .NET MAUI ListView control

Creating a news feed app using .NET MAUI ListView control

GitHub reference

For more details, refer to creating a news feed app using the .NET MAUI ListView GitHub demo.

Conclusion

Thanks for reading! In this blog, we’ve seen how to create a news feed app using the Syncfusion .NET MAUI ListView control. Try out the steps given in this blog and provide a seamless news browsing experience.

The existing customers can download the new version of Essential Studio on the License and Downloads page. If you are not a Syncfusion customer, try our 30-day free trial to check out our incredible features.

You can also contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!

Related blogs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .