使用MVVM模式,我有一个Model,viewmodel和View,它包含一个ListView. ListView绑定到viewmodel的成员,该成员是Model类的ObservableCollection.我可以使初始显示的绑定工作,并且可以在对视图执行操作时更新适当行的Model类的属性,但是我无法刷新视图,从ObservableCollection中的Model类中提取数据. ListView类不包含使无效或强制刷新的方法,这将解决我的问题.更新模型上的数据后,如何刷新ListView?
这是我想要做的一个简单示例:每行包含一个Button和Label.单击按钮后,我可以更新标签,该标签将反映在屏幕上.我需要做的是更新模型,反过来应该强制更新视图.但是,我不能让这个工作.在实际应用程序中,Model的更新将在业务逻辑层中,而不是在视图中,之后我需要强制刷新ListView.
示例代码:
using System; using System.Collections.ObjectModel; using Xamarin.Forms; namespace ListViewTest { public class Model { public static int ids = 0; public Model(string count) { Id = +1; Count = count; } public int Id { get; set; } public string Count { get; set; } } public class ModelList : ObservableCollection<Model> { } public class viewmodel { ModelList list = new ModelList(); public ModelList viewmodelList { get { return list; } set { list = value; } } } public partial class MainPage : ContentPage { public viewmodel viewmodel; public class DataCell : ViewCell { public DataCell() { var Btn = new Button(); Btn.Text = "Click"; var Data = new Label(); Data.SetBinding(Label.TextProperty,"Count"); Btn.Clicked += (object sender,EventArgs e) => { Model model = (Model)(((Button)sender).Parent.BindingContext); int count = Convert.ToInt32(model.Count); count++; model.Count = count.ToString(); // Need to refresh ListView from data source here... How??? }; StackLayout s = new StackLayout(); s.Orientation = StackOrientation.Horizontal; s.Children.Add(Btn); s.Children.Add(Data); this.View = s; } } public MainPage () { viewmodel = new viewmodel(); viewmodel.viewmodelList.Add(new Model("0")); viewmodel.viewmodelList.Add(new Model("0")); InitializeComponent(); } public void InitializeComponent() { ListView listView = new ListView { ItemsSource = viewmodel.viewmodelList,ItemTemplate = new DataTemplate(() => { return new DataCell(); }) }; Content = listView; } } }
解决方法
我认为你的模型需要实现INotifyPropertyChanged.因此,UI知道模型中的值已更改
这样的事情:
public class Model : INotifyPropertyChanged { // boiler-plate public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this,new PropertyChangedEventArgs(propertyName)); } protected bool SetField<T>(ref T field,T value,string propertyName) { if (EqualityComparer<T>.Default.Equals(field,value)) return false; field = value; OnPropertyChanged(propertyName); return true; } // props private string _count; public string Count { get { return _count; } set { SetField(ref _count,value,"Count"); } } }