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?
CodePudding user response:
You should use an IEnumerable
collection that sends property change notifications(such as ObservableCollection) for the ItemsSource, then simply add to the underlying collection.
Here's an example:
ObservableCollection<string> tasks = new();
taskList.ItemsSource = tasks;
tasks.Add("Do something");
CodePudding user response:
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.