Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用ListView SelectedItem vs TextCell命令绑定_C#_Xaml_Xamarin_Mvvm_Xamarin.forms - Fatal编程技术网

C# 使用ListView SelectedItem vs TextCell命令绑定

C# 使用ListView SelectedItem vs TextCell命令绑定,c#,xaml,xamarin,mvvm,xamarin.forms,C#,Xaml,Xamarin,Mvvm,Xamarin.forms,我有一个场景,需要获取所选TextCell的值,并使用它更新ListView之外的标签。我注意到ListView有一个SelectedItem属性,TextCell有一个Command属性。这两者有什么区别 作为一个更一般的设计问题(我使用的是XamarinMVVM),我应该如何进行更新?目前我正在考虑使用ListView SelectedItem属性并将其与我的VM绑定(双向)。然后在Setter中,我将更新标签绑定到的VM属性。。。。问题是我需要执行一个异步任务,因为它会将TextCell值

我有一个场景,需要获取所选TextCell的值,并使用它更新ListView之外的标签。我注意到ListView有一个SelectedItem属性,TextCell有一个Command属性。这两者有什么区别

作为一个更一般的设计问题(我使用的是XamarinMVVM),我应该如何进行更新?目前我正在考虑使用ListView SelectedItem属性并将其与我的VM绑定(双向)。然后在Setter中,我将更新标签绑定到的VM属性。。。。问题是我需要执行一个异步任务,因为它会将TextCell值转换为我需要的标签值。。。。我该怎么做

我看到有人提到行为,但这似乎更多是针对UI(而不是逻辑)。我还考虑了使用Task.Run来解决setter中的异步问题,但很明显,异步项并不适用于setter。此外,我还考虑过使用MessagingCenter,但这似乎适用于VM->VM。TextCell命令似乎合适,但已读取以使用SelectedItems

视图:

  • 将标签绑定到虚拟机的属性,例如文本
  • 将ListView的SelectedItem绑定到VM的属性,我们称之为SelectedItem
  • 在SelectedItem的setter中调用Task。运行(()=>DoWork(value))完成工作或获取翻译
  • 在工作结束时,设置属性文本
  • 文本的属性设置程序应调用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);
        }
    }
}

所以任务。在setter中运行很好。。。很公平。谢谢。Task.Run的目的是将其放在UI以外的其他线程上吗?我一直只在异步方法中使用它。
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;
        }
    }
}
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);
        }
    }
}