Xamarin Forms 中的数据绑定问题
DataBinding issue in Xamarin Forms
我有一个新的 Xamarin Forms 5 应用程序,但在数据绑定方面遇到了问题。
首先,我显示一条消息,告诉用户他的列表中有多少项。最初,这是 0。它由视图模型的 DisplayMessage
属性 显示。
然后,调用 Init()
方法,一旦 API 调用完成,MyList
中就会有一些项目。我放置了断点以确保 API 调用有效,并且我最终在 MyList
属性.
中得到了一些数据
因为我在我的 Init()
方法中更改了 message
的值,所以我希望消息会更改并显示列表中的项目数,但它并没有改变,即使我有一些MyList
.
中的项目
我创建了一个新的 ViewModel,如下所示:
public class MyViewModel : BaseViewModel
{
public List<MyItem> MyList { get; set; } = new List<MyItem>();
string message = "You have no items in your list... ";
public string DisplayMessage
{
get => message;
set
{
if(message == value)
return;
message = value;
OnPropertyChanged();
}
}
public async void Init()
{
var data = await _myService.GetData();
if(data.Count > 0)
message = $"You have {data.Count} items in your list!";
MyList = data;
}
}
我的 MainPage
后面的代码如下所示:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
MyViewModel _vm;
MainPage()
{
InitializeComponent();
_vm = new MyViewModel();
this.BindingContext = _vm;
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.Init();
}
}
我没有更改基本视图模型中的任何内容,只是添加了我的服务,它看起来像这样:
public class BaseViewModel : INotifyPropertyChanged
{
public IMyApiService MyApi => DependencyService.Get<IMyApiService>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
我很感激有人告诉我我的错误在哪里。谢谢。
没有看到 Xaml,我无法 100% 回答,但我看到了以下几点:
- 您正在通过字段设置“消息”,而不是 属性。由于您是直接设置字段,因此不会触发 OnPropertyChanged 事件,因此 UI 不会收到值已更改的通知。
- 我猜您正在将“MyList”绑定到某种 CollectionView 或其他东西?如果它是只读视图,则可以使用列表,因为该集合永远不会更新。但是,如果您计划在运行时添加或删除项目,出于与上述相同的原因,它需要是一个“ObservableCollection”,UI 不会收到列表中新项目的通知,但 ObservableCollection 会通知UI 的更改,因此它可以更新。
- Jason 在他的评论中提到了上面的内容。 MyList 属性 应该像使用 OnPropertyChanged 的其他属性一样设置。
我有一个新的 Xamarin Forms 5 应用程序,但在数据绑定方面遇到了问题。
首先,我显示一条消息,告诉用户他的列表中有多少项。最初,这是 0。它由视图模型的 DisplayMessage
属性 显示。
然后,调用 Init()
方法,一旦 API 调用完成,MyList
中就会有一些项目。我放置了断点以确保 API 调用有效,并且我最终在 MyList
属性.
因为我在我的 Init()
方法中更改了 message
的值,所以我希望消息会更改并显示列表中的项目数,但它并没有改变,即使我有一些MyList
.
我创建了一个新的 ViewModel,如下所示:
public class MyViewModel : BaseViewModel
{
public List<MyItem> MyList { get; set; } = new List<MyItem>();
string message = "You have no items in your list... ";
public string DisplayMessage
{
get => message;
set
{
if(message == value)
return;
message = value;
OnPropertyChanged();
}
}
public async void Init()
{
var data = await _myService.GetData();
if(data.Count > 0)
message = $"You have {data.Count} items in your list!";
MyList = data;
}
}
我的 MainPage
后面的代码如下所示:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
MyViewModel _vm;
MainPage()
{
InitializeComponent();
_vm = new MyViewModel();
this.BindingContext = _vm;
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.Init();
}
}
我没有更改基本视图模型中的任何内容,只是添加了我的服务,它看起来像这样:
public class BaseViewModel : INotifyPropertyChanged
{
public IMyApiService MyApi => DependencyService.Get<IMyApiService>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
我很感激有人告诉我我的错误在哪里。谢谢。
没有看到 Xaml,我无法 100% 回答,但我看到了以下几点:
- 您正在通过字段设置“消息”,而不是 属性。由于您是直接设置字段,因此不会触发 OnPropertyChanged 事件,因此 UI 不会收到值已更改的通知。
- 我猜您正在将“MyList”绑定到某种 CollectionView 或其他东西?如果它是只读视图,则可以使用列表,因为该集合永远不会更新。但是,如果您计划在运行时添加或删除项目,出于与上述相同的原因,它需要是一个“ObservableCollection”,UI 不会收到列表中新项目的通知,但 ObservableCollection 会通知UI 的更改,因此它可以更新。
- Jason 在他的评论中提到了上面的内容。 MyList 属性 应该像使用 OnPropertyChanged 的其他属性一样设置。