XAML自定义集合绑定异步集合更新

时间:2014-12-02 05:59:28

标签: c# mvvm data-binding observablecollection inotifypropertychanged

我有一个继承自ObservableCollectionINotifyPropertyChanged的自定义类(即自定义类也有属性),用作Collection<T> T 还< / em>继承自INotifyPropertyChanged

public class CustomCollection<T> : ObservableCollection<T>, INotifyPropertyChanged where T: INotifyPropertyChanged {
private string _name;
public string Name {
    get {
        return _name;
    }
    set {
        if (_name != value) {
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }
}

private int _total;
public int Total {
    get {
        return _total;
    }
    set {
        if (_total != value) {
            _total = value;
            NotifyPropertyChanged("Total");
        }
    }
}

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName) {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (null != handler) {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

T项目类:

public class DataItem : INotifyPropertyChanged {

    private string _fname;
    public string Fname {
        get {
            return _fname;
        }
        set {
            if (value != _fname) {
                _fname = value;
                NotifyPropertyChanged("Fname");
            }
        }
    }

    private int_value;
    public int Value {
        get {
            return _value;
        }
        set {
            if (value != _value) {
                _value = value;
                NotifyPropertyChanged("Value");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ViewModel

public class ViewModel : ViewModelBase {
    private readonly IService _dataService;

    private bool _isLoading;
    public bool IsLoading {
        get {
            return _isLoading;
        }
        private set {
            _isLoading = value;
            RaisePropertyChanged("IsLoading");
        }
    }

    private CustomCollection<DataItem> _items;
    public CustomCollection<DataItem> Items
    {
        get
        {
            return _items;
        }
        set
        {
            _items= value;
            RaisePropertyChanged("Items");
        }
    }

    public ViewModel(IService dataService) {
        _dataService = dataService;
    }

    public void Refresh() {
        if (!this.IsLoading) {
            this.IsLoading = true;

            _dataService.RefreshData(
                this, (error) => {
                    if (error != null) {
                        return;
                    }

                    if (!IsInDesignMode)
                        this.IsLoading = false;
                }
            );
        }
    }
    public void GetData() {
        if (Games == null) {
            Games = new CustomCollection<DataItem>();
        } else {
            Games.Clear();
        }

        if (!this.IsLoading) {
            this.IsLoading = true;

            _dataService.GetData(
                this, (error) => {
                    if (error != null) {
                        return;
                    }

                    if (!IsInDesignMode)
                        this.IsLoading = false;
                }
            );
        }
    }

我已将CustomCollection<T>绑定到我的视图中的控件(xaml)。一切正常,导航到页面后,ViewModel要求DataService检索数据并填充CustomCollection<T>。但是,在刷新数据时,视图更新,直到所有数据被迭代并刷新/更新!

以下是刷新/更新的代码(请记住,我通过Web服务检索数据,并且出于测试目的,只需手动更新Value属性DataItem 1}}在每个CustomCollection<T>的逾越节中:

public async RefreshData(ViewModel model, Action<Exception> callback) {
    if (model.Items == null) return;

    // ... retrieve data from web service here (omitted) ...

    foreach (DataItem item in retrievedItems) { // loop for each item in retrieved items
        DataItem newItem = new DataItem() { Fname = item.Fname, Value = item.Value };
        if (model.Items.contains(newItem)) { // override for .Equals in CustomCollection<T> allows for comparison by just Fname property
            model.Items[model.Items.IndexOf(newItem)].Value += 10; // manual update
        } else {
            model.Items.Add(newItem);
        }
        System.Threading.Thread.Sleep(1000); // 1 second pause to "see" each item updated sequentially...
    }
    callback(null);
}

总而言之,我如何才能做到这一点,以便更新Value我的DataItem立即反映在视图中,因为我目前的CustomCollection<DateItem>设置?或许与async有关?我的意思是,当Sleep(1000)被调用时,用户界面会挂起,这可能与它有关吗?

有关如何解决此问题的任何想法?您可能已经猜到,首次检索数据时也会出现此问题(但在导航到View期间检索/处理数据时几乎不会注意到这一点。)

注意:我使用MVVMLight Toolkit

感谢。

0 个答案:

没有答案