What i am doing is passing data through more than 2 pages. I assign viewmodel to next page while i am navigating. In second page i have a listview that is not refreshing/updating after adding a value.
Help me please!!
Here is my code
MyViewModel
public class MyViewModel : INotifyPropertyChanged
{
public string _userName { get; set; }
public List<family> familyList;
public List<family> FamilyList
{
get { return familyList; }
set
{
familyList = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public MyViewModel()
{
_userName = "Mak";
familyList = new List<family>();
}
public void AddMember(string memberName)
{
FamilyList.Add(new family
{
name = memberName,
id = Guid.NewGuid().ToString(),
username=_userName
});
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
userdetails.xaml
<cl:BasePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="familyinfo.userdetails" xmlns:cl="clr-namespace:familyinfo;assembly=familyinfo">
<Label Font="Roboto-Medium" FontSize="14" Text="{Bindinbg _userName}" />
<Button Clicked="Next_Step" HeightRequest="30" HorizontalOptions="FillAndExpand" BorderRadius="12" Text="NEXT" />
</cl:BasePage>
userdetails.xaml.cs
public partial class userdetails : BasePage
{
public MyViewModel _myViewModel { get; set; }
public userdetails()
{
InitializeComponent();
BindingContext = new MyViewModel();
}
void Next_Step(object sender, System.EventArgs e)
{
_myViewModel =(MyViewModel) this.BindingContext;
var familyMember = new FamilyMember();
familyMember.BindingContext = _myViewModel;
Application.Current.MainPage = new NavPage(registerCar);
}
}
FamilyMember.xaml
<cl:BasePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="familyinfo.FamilyMember" xmlns:cl="clr-namespace:familyinfo;assembly=familyinfo">
<Label Font="Roboto-Medium" FontSize="14" Text="{Bindinbg _userName}" />
<cl:CustomEntry x:Name="txtMemberName" Placeholder="Member Name" FontSize="12" />
<Button Clicked="AddMember" HeightRequest="30" HorizontalOptions="FillAndExpand" BorderRadius="12" Text="Add" />
<ListView ItemsSource="{Binding FamilyList}" VerticalOptions="FillAndExpand" BackgroundColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid Padding="20,10,0,0" ColumnSpacing="12" RowSpacing="0" BackgroundColor="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto">
</RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding name}" Grid.Column="0" Font="Roboto-Medium" FontSize="14" TextColor="#000000" />
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</cl:BasePage>
FamilyMember.xaml.cs
public partial class FamilyMember : BasePage
{
public MyViewModel _myViewModel { get; set; }
public userdetails()
{
InitializeComponent();
}
void AddMember(object sender, System.EventArgs e)
{
_myViewModel = (MyViewModel)this.BindingContext;
_myViewModel.AddMember(txtMemberName.Text);
}
}
I agree with Atul: Using an ObservableCollection
is the right way to do it.
A workaround - if you don't have a chance to change that - is to set the ListView
's ItemSource
to null
and back to the list, whenever data changed and the UI needs to update:
void UpdateListView(ListView listView)
{
var itemsSource = listView.ItemsSource;
listView.ItemsSource = null;
listView.ItemsSource = itemsSource;
}
In fact, you must use a collection that implements INotifyCollectionChanged
interface (instead of the well known INofifyPropertyChanged
). And that's exactly what does ObservableCollection<T>
for you. This is why it works like "magic".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With