使用ListView SelectedItem与TextCell命令绑定

时间:2018-02-25 20:08:31

标签: c# xaml xamarin mvvm xamarin.forms

我有一个场景,我需要获取所选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;

1 个答案:

答案 0 :(得分:1)

  • 您将标签绑定到您的属性VM让我们说文本
  • 您将ListView的SelectedItem绑定到VM的属性,我们称之为SelectedItem
  • 在SelectedItem的setter中,您调用Task.Run(()=&gt; DoWork(value))来完成您的工作或获取您的翻译
  • 在工作结束时,您需要设置属性文本
  • Text的Property Setter应该调用PropertyChanged
  • 就是这样

示例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);
        }
    }
}