Search code examples
c#xamlmaui

How to refresh XAML view in MAUI?


I'm making an app where I have layouts generate dynamically based on a list.

<StackLayout>
        <CollectionView x:Name="taskList">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Task">
                    <VerticalStackLayout Margin="15">
                        <Entry Text="{Binding name}" IsReadOnly="True" />
                        <Entry Text="{Binding departmentsString}" IsReadOnly="True"/>
                        <HorizontalStackLayout>
                            <Entry Text="{Binding status}" IsReadOnly="True"/>
                            <Entry Text="{Binding deadline}" IsReadOnly="True" />
                            <Entry Text="{Binding author.fullName}" IsReadOnly="True"/>
                        </HorizontalStackLayout>
                        <Entry Text="{Binding description}" IsReadOnly="True" />
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

The list is bonded like this:

taskList.ItemsSource = company.tasks;

I want to refresh this whenever I add new items to the list.

I tried rebinding the list to the ItemsSource but it just didn't work:

taskList.ItemsSource = company.tasks;

How should I do it? Can I just refresh the view so it generates everything again?


Solution

  • Instead of assigning the ItemsSource from code-behind, you should bind a custom collection, which makes it much easier and decouples the UI and logic. Read more over the MVVM pattern.

    (I don't have a IDE here, so it's not tested)

    You could do something like:

    // data class
    public class TaskInfo
    {
        public string name {get; set;}
        public string departmentsString {get;set;}
    }
    

    // you page/view whatever code behind the xaml
    public class YourPage : // insert the class which it is derived from.
    {
       // create a collection property, which generates events when changed. The UI react on these events.
       public ObservableCollection<TaskInfo> Tasks {get;} = new();
    
       public YourPage()
       {
          InitComponentsOrSomething();
          // assign the datacontext (which the view binds to)
          this.DataContext = this;
       }
    }
    

    And your xaml would be something like this: (mind the Binding instead of the name)

    <StackLayout>
        <CollectionView ItemsSource="{Binding Tasks}">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Task">
                    <VerticalStackLayout Margin="15">
                        <Entry Text="{Binding name}" IsReadOnly="True" />
                        <Entry Text="{Binding departmentsString}" IsReadOnly="True"/>
                        <HorizontalStackLayout>
                            <Entry Text="{Binding status}" IsReadOnly="True"/>
                            <Entry Text="{Binding deadline}" IsReadOnly="True" />
                            <Entry Text="{Binding author.fullName}" IsReadOnly="True"/>
                        </HorizontalStackLayout>
                        <Entry Text="{Binding description}" IsReadOnly="True" />
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
    

    If you want to add items to the collection, just use the Tasks property:

    Tasks.Add(new TaskInfo { name = "some name", departmentsString = "Enter here" });
    

    ps: I would not call a data object 'Task', either give it a better description. TaskInfo/CompanyTask.