Xamarin 表单更新 listView itemSource
Xamarin form update listView itemSource
好的,我有一个 ListView
对象,它有一个 List<Filiale>
作为 ItemSource
,我想在对象列表更改时刷新 ItemSource
。 ListView 具有个性化 ItemTemplate
现在我已经这样做了:
public NearMe ()
{
list=jM.ReadData ();
listView.ItemsSource = list;
listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
searchBar = new SearchBar {
Placeholder="Search"
};
searchBar.TextChanged += (sender, e) => {
TextChanged(searchBar.Text);
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add (searchBar);
stack.Children.Add (listView);
Content = stack;
}
public void TextChanged(String text){
//DOSOMETHING
list=newList;
}
正如您在 TextChanged 方法中看到的那样,我将一个新列表分配给前一个列表,但视图中没有任何变化。
在我创建的 ViewCell
中,我将标签的文本字段分配给 SetBinding
将列表更改为 ObservableCollection 并实施 INotifyPropertyChanged 以使更改反映在您的 ListView 中。
您可以定义一个基础视图模型并从 INotifyPropertyChanged 继承它
public abstract class BaseViewModel : INotifyPropertyChanged
{
protected bool ChangeAndNotify<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
{
if (!EqualityComparer<T>.Default.Equals(property, value))
{
property = value;
NotifyPropertyChanged(propertyName);
return true;
}
return false;
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
然后在您的视图模型中(例如 JM)将从 BaseViewModel
继承
并且可以创建 ObservableCollection<YOURLISTCLASS>
列表
您在 ViewModel(例如 JM)中的字段也应该像下面这样实现:
public const string FirstNamePropertyName = "FirstName";
private string firstName = string.Empty;
public string FirstName
{
get { return firstName; }
set { this.ChangeAndNotify(ref this.firstName, value, FirstNamePropertyName); }
}
希望对您有所帮助。
好的,这就是我解决问题的方法,首先,我创建了一个 "wrapper",它实现了 INotifyPropertyChanged
列表,我将其作为 ItemSource,如下所示:
public class Wrapper : INotifyPropertyChanged
{
List<Filiale> list;
JsonManager jM = new JsonManager ();//retrieve the list
public event PropertyChangedEventHandler PropertyChanged;
public NearMeViewModel ()
{
list = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();//initialize the list
}
public List<Filiale> List{ //Property that will be used to get and set the item
get{ return list; }
set{
list = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("List"));// Throw!!
}
}
}
public void Reinitialize(){ // mymethod
List = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();
}
然后在 NearMe class:
Wrapper nearMeVM = new Wrapper();
public NearMe ()
{
Binding myBinding = new Binding("List");
myBinding.Source = nearMeVM;
myBinding.Path ="List";
myBinding.Mode = BindingMode.TwoWay;
listView.SetBinding (ListView.ItemsSourceProperty, myBinding);
listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
searchBar = new SearchBar {
Placeholder="Search"
};
searchBar.TextChanged += (sender, e) => {
TextChanged(searchBar.Text);
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add (searchBar);
stack.Children.Add (listView);
Content = stack;
}
public void TextChanged(String text){
if (!String.IsNullOrEmpty (text)) {
text = text [0].ToString ().ToUpper () + text.Substring (1);
var filterSedi = nearMeVM.List.Where (filiale => filiale.nome.Contains (text));
var newList = filterSedi.ToList ();
nearMeVM.List = newList.OrderBy (x => x.distanza).ToList ();
} else {
nearMeVM.Reinitialize ();
}
您可以将 ListView 的 ItemsSource 设置为 null,然后再次将其设置回来,这样会 table 重新加载。
http://forums.xamarin.com/discussion/18868/tableview-reloaddata-equivalent-for-listview
这是我目前从我正在开发的应用程序中提取的此模式的实现,尽可能简洁。
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MyNamespace
{
// This base view model takes care of implementing INotifyPropertyChanged
// In your extended View Model classes, use SetValue in your setters.
// This will take care of notifying your ObservableCollection and hence
// updating your UI bound to that collection when your view models change.
public abstract class BaseViewModel : INotifyPropertyChanged
{
protected void SetValue(ref T backingField, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(backingField, value)) return;
backingField = value;
OnPropertyChanged(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// Using MvvM, this would likely be a View Model class.
// However, it could also be a simple POCO model class
public class MyListItem : BaseViewModel
{
private string _itemLabel = "List Item Label";
public string Label
{
get => _itemLabel;
set => SetValue(ref _itemLabel, value);
}
}
// This is your MvvM View Model
// This would typically be your BindingContext on your Page that includes your List View
public class MyViewModel : BaseViewModel
{
private ObservableCollection _myListItemCollection
= new ObservableCollection();
public ObservableCollection MyListItemCollection
{
get { return _myListItemCollection; }
set => SetValue(ref _myListItemCollection, value);
}
}
}
只需将 System.Collections.Generic.List
转换为 System.Collections.ObjectModel.ObservableCollection
,然后再绑定到 ListView
。
好的,我有一个 ListView
对象,它有一个 List<Filiale>
作为 ItemSource
,我想在对象列表更改时刷新 ItemSource
。 ListView 具有个性化 ItemTemplate
现在我已经这样做了:
public NearMe ()
{
list=jM.ReadData ();
listView.ItemsSource = list;
listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
searchBar = new SearchBar {
Placeholder="Search"
};
searchBar.TextChanged += (sender, e) => {
TextChanged(searchBar.Text);
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add (searchBar);
stack.Children.Add (listView);
Content = stack;
}
public void TextChanged(String text){
//DOSOMETHING
list=newList;
}
正如您在 TextChanged 方法中看到的那样,我将一个新列表分配给前一个列表,但视图中没有任何变化。
在我创建的 ViewCell
中,我将标签的文本字段分配给 SetBinding
将列表更改为 ObservableCollection 并实施 INotifyPropertyChanged 以使更改反映在您的 ListView 中。
您可以定义一个基础视图模型并从 INotifyPropertyChanged 继承它
public abstract class BaseViewModel : INotifyPropertyChanged
{
protected bool ChangeAndNotify<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
{
if (!EqualityComparer<T>.Default.Equals(property, value))
{
property = value;
NotifyPropertyChanged(propertyName);
return true;
}
return false;
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
然后在您的视图模型中(例如 JM)将从 BaseViewModel
继承
并且可以创建 ObservableCollection<YOURLISTCLASS>
列表
您在 ViewModel(例如 JM)中的字段也应该像下面这样实现:
public const string FirstNamePropertyName = "FirstName";
private string firstName = string.Empty;
public string FirstName
{
get { return firstName; }
set { this.ChangeAndNotify(ref this.firstName, value, FirstNamePropertyName); }
}
希望对您有所帮助。
好的,这就是我解决问题的方法,首先,我创建了一个 "wrapper",它实现了 INotifyPropertyChanged
列表,我将其作为 ItemSource,如下所示:
public class Wrapper : INotifyPropertyChanged
{
List<Filiale> list;
JsonManager jM = new JsonManager ();//retrieve the list
public event PropertyChangedEventHandler PropertyChanged;
public NearMeViewModel ()
{
list = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();//initialize the list
}
public List<Filiale> List{ //Property that will be used to get and set the item
get{ return list; }
set{
list = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("List"));// Throw!!
}
}
}
public void Reinitialize(){ // mymethod
List = (jM.ReadData ()).OrderBy (x => x.distanza).ToList();
}
然后在 NearMe class:
Wrapper nearMeVM = new Wrapper();
public NearMe ()
{
Binding myBinding = new Binding("List");
myBinding.Source = nearMeVM;
myBinding.Path ="List";
myBinding.Mode = BindingMode.TwoWay;
listView.SetBinding (ListView.ItemsSourceProperty, myBinding);
listView.ItemTemplate = new DataTemplate(typeof(FilialeCell));
searchBar = new SearchBar {
Placeholder="Search"
};
searchBar.TextChanged += (sender, e) => {
TextChanged(searchBar.Text);
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add (searchBar);
stack.Children.Add (listView);
Content = stack;
}
public void TextChanged(String text){
if (!String.IsNullOrEmpty (text)) {
text = text [0].ToString ().ToUpper () + text.Substring (1);
var filterSedi = nearMeVM.List.Where (filiale => filiale.nome.Contains (text));
var newList = filterSedi.ToList ();
nearMeVM.List = newList.OrderBy (x => x.distanza).ToList ();
} else {
nearMeVM.Reinitialize ();
}
您可以将 ListView 的 ItemsSource 设置为 null,然后再次将其设置回来,这样会 table 重新加载。 http://forums.xamarin.com/discussion/18868/tableview-reloaddata-equivalent-for-listview
这是我目前从我正在开发的应用程序中提取的此模式的实现,尽可能简洁。
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MyNamespace
{
// This base view model takes care of implementing INotifyPropertyChanged
// In your extended View Model classes, use SetValue in your setters.
// This will take care of notifying your ObservableCollection and hence
// updating your UI bound to that collection when your view models change.
public abstract class BaseViewModel : INotifyPropertyChanged
{
protected void SetValue(ref T backingField, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(backingField, value)) return;
backingField = value;
OnPropertyChanged(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// Using MvvM, this would likely be a View Model class.
// However, it could also be a simple POCO model class
public class MyListItem : BaseViewModel
{
private string _itemLabel = "List Item Label";
public string Label
{
get => _itemLabel;
set => SetValue(ref _itemLabel, value);
}
}
// This is your MvvM View Model
// This would typically be your BindingContext on your Page that includes your List View
public class MyViewModel : BaseViewModel
{
private ObservableCollection _myListItemCollection
= new ObservableCollection();
public ObservableCollection MyListItemCollection
{
get { return _myListItemCollection; }
set => SetValue(ref _myListItemCollection, value);
}
}
}
只需将 System.Collections.Generic.List
转换为 System.Collections.ObjectModel.ObservableCollection
,然后再绑定到 ListView
。