我有一个场景,我需要获取所选TextCell的值,并使用它来更新ListView之外的Label。我注意到ListView有一个SelectedItem属性,TextCell有一个Command属性。这些有什么区别?
作为更一般的设计问题(我使用Xamarin MVVM),我该如何进行更新?目前我正在考虑使用ListView SelectedItem属性并将其与我的VM绑定(双向)。然后在Setter中我会更新标签绑定的VM属性....问题是我有一个异步任务我需要做,因为它会将TextCell值转换为我需要的Label值。 ......我该怎么做?
我已经看到了行为的提及,但对于UI(而不是逻辑)来说似乎更多。我也想过使用Task.Run来解决setter中的异步问题,但很明显异步项并不适用于setter。我还想过使用MessagingCenter,但这似乎适用于VM - > VM。 TextCell命令似乎是合适的,但已经读过使用SelectedItems。
查看:
<ListView x:Name="ResultsList"
SelectedItem="{Binding SelectedDestinationItem,
Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Description}" Detail="{Binding Place_ID}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Text="{Binding Current.Destination}"/>
对于VM:
public AutoCompletePrediction SelectedDestinationItem
{
get => _selectedDestinationItem;
set
{
SetProperty(ref _selectedDestinationItem, value, "SelectedDestinationItem");
if (_selectedDestinationItem == null) return;
//not valid
var place = await Places.GetPlace(_selectedDestinationItem.Place_ID, Constants.PlacesApiKey);
Current.Destination = place;
SelectedDestinationItem = null;
}
}
private AutoCompletePrediction _selectedDestinationItem;
答案 0 :(得分:1)
示例VM:
public class MyViewModel : ViewModelBase {
private string _text;
public string Text {
get => _text;
set {
_text = value;
OnPropertyChanged();
}
}
private YourItemType _selectedItem;
public YourItemType SelectedItem {
get => _selectedItem;
set {
_selectedItem = value;
Task.Run(() => GetValue(value));
OnPropertyChanged();
}
}
private readonly object _lockObject = new object();
private void GetValue(YourItemType item){
if(item == null) {
Text = "invalid";
return;
}
//avoid entering twice here
lock(_lockObject) {
//Do your work here - it's in the background already
Text = resultOfWork;
}
}
}
OnPropertyChanged()是INotifyPropertyChanged的实现。类似的东西:
public class ViewModelBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChangedByName(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void RefreshView() {
foreach (var propertyInfo in GetType().GetRuntimeProperties()) {
OnPropertyChangedByName(propertyInfo.Name);
}
}
}