【问题标题】:Binding with ListView SelectedItem vs TextCell Command与 ListView SelectedItem 与 TextCell 命令绑定
【发布时间】:2018-08-05 06:50:46
【问题描述】:

我有一个场景,我需要获取选定 TextCell 的值并使用它来更新 ListView 之外的标签。我注意到 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}"/>

对于虚拟机:

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;

【问题讨论】:

    标签: c# xaml xamarin mvvm xamarin.forms


    【解决方案1】:
    • 你将你的标签绑定到你的虚拟机的一个属性让我们说文本
    • 您将 ListView 的 SelectedItem 绑定到 VM 的属性,我们称之为 SelectedItem
    • 在 SelectedItem 的设置器中,您调用 Task.Run(() => DoWork(value)) 来完成工作或获取翻译
    • 在工作结束时设置属性文本
    • Text 的 Property Setter 应该调用 PropertyChanged
    • 就是这样

    示例虚拟机:

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

    【讨论】:

    • 所以 Task.Run 在 setter 中很好......很公平。谢谢。
    • Task.Run 的目的是把它放到 UI 以外的不同线程上吗?我一直只使用异步方法。
    猜你喜欢
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 2018-07-07
    • 2023-03-25
    • 1970-01-01
    • 2014-09-23
    相关资源
    最近更新 更多