【问题标题】:ObservableCollection not showing up in UIObservableCollection 未显示在 UI 中
【发布时间】:2016-11-08 20:52:13
【问题描述】:

我正在尝试在 XAML 中显示项目列表。我从公共 API 获取列表,将其转换为我需要的类,然后我想显示它。

public static async Task PopulateListAsync(ObservableCollection<MyClass> myList) {
    var listContainer = await GetListAsync();

    foreach (var item in listContainer) {
        //converting from one class to another, editing some properties and such
        myList.Add(item );
    }
}

在我的 MainPage.cs 上

public ObservableCollection<MyClass> Value { get; set; }

public MainPage() {
    this.InitializeComponent();
    Value = new ObservableCollection<MyClass>();
}

private async void Page_Loaded(object sender, RoutedEventArgs e) {
    await PopulateListAsync(Value);
}

而且我在 XAML 中显示很好。

但后来我想介绍过滤。所以我得到数据,将它们转换为某个类并将它们插入到一个列表中,然后我使用 LINQ 进行过滤(似乎比在 ObservableCollection 中过滤更容易)。

基本上,我将PopulateListAsync() 替换为FormatListAsync(),而不是将数据直接插入ObservableCollection&lt;&gt;,而是返回List&lt;&gt;。然后我有一个“中间人”功能

public static async Task PopulateListAsync(ObservableCollection<MyClass> myList) {
    myList = new ObservableCollection<MyClass>(await FormatListAsync());
    //filtering itself isn't implemented yet, but it would be placed here
}

我可能只是循环使用mylist 并将其逐个添加到ObservableCollection&lt;&gt; 中,但我觉得肯定有更好的方法。

我想我应该实现一些 PropertyChanged 事件或类似的东西,但我尝试了一些(例如this one),但没有成功。我觉得我不太明白如何实现它。

【问题讨论】:

  • 我不认为你可以做 Value = new ObservableCollection();因为 Value 属性是字符串类型。可能是错字?
  • 只是一个错字。对不起。
  • 您缺少可观察集合的 OnPropertyChange

标签: c# wpf xaml


【解决方案1】:

如果您为方法参数分配新值,那么您只需将引用的副本更改为集合而不更改源引用。你可以阅读更多关于passing reference types as method parameters on MSDN的信息。

此外,如果您要更改的属性本身没有实现 INotifyPropertyChanged,那么您的 UI 将不会发生任何变化,因为您的视图不知道这些变化。

您可以通过简单易行的方式操作源集合,而不是创建新集合。只需做类似的事情

public static async Task PopulateListAsync(ObservableCollection<MyClass> myList) 
{
    // newList can be an List<MyClass> type, not ObservableCollection
    var newList = await FormatListAsync();

    // change displayed list with new data
    myList.Clear();
    foreach(var newValue in newList)
        myList.Add(newValue);
}

另一个选项,您可以为您的 ViewModel 实现 INotifyPropertyChanged 并在 Value 属性的设置器中引发 PropertyChanged 事件:

private ObservableCollection<MyClass> _value; 
public ObservableCollection<MyClass> Value 
{ 
    get
    {
        return _value;
    } 
    set
    {
        // I hope this line of code will convince you to give more clear variable name
        if(value != _value)
        {
            _value = value;
            NotifyPropertyChanged(nameof(Value));
        } 
    }
}

另外,您需要直接在PopulateListAsync() 中分配Value

public static async Task PopulateListAsync() 
{
    Value = new ObservableCollection<MyClass>(await FormatListAsync());
}

【讨论】:

  • 我想到了第一种做事方式。我想知道是否有更好的方法。关于NotifyPropertyChanged - 我可以在不使用 MVVM 模式的情况下实现它吗?这是我在 C# 中的第一个合适的项目,我真的放弃了 MVVM,因为我无法让它工作。
  • @rancor1223 好吧,MVVM 是更好的方法 :) 此外,如果您要更改整个列表,则不需要使用 ObservableCollection,那么您的属性可能具有 List&lt;MyClass&gt; 类型。如果您想动态操作集合(使用 clear、add 和其他方法),请使用 ObservableCollection。好的,您可以为您的对象实现 INPC,该对象不是单独的类,而是您的视图的数据源。此外,直接操作控件及其属性还有一个非常糟糕的方法:ObservableCollection&lt;MyData&gt; data = new ObservableCollection&lt;MyData&gt;(...); ListBox.ItemsSource = data;
  • 我下次再试试MVVM。现在对我来说太多了:)。我会看到只使用List&lt;&gt;,虽然我认为ObservableCollection&lt;&gt; 给了我空间,以便以后在需要时使用它。非常感谢您的帮助!
猜你喜欢
  • 2019-05-02
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 2013-01-02
  • 2021-02-20
  • 2020-09-14
相关资源
最近更新 更多