1

I'm trying to display list of items in XAML. I get the list from public API, convert it to the class I need and then I want to display it.

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

and on the MainPage.cs I had

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

And I displayed in the XAML fine.

But then I wanted to introduce filtering. So I get the data, convert them to some class and insert them to a list, which I then filter with LINQ (seems easier then filtering in ObservableCollection).

Basically I replaced the PopulateListAsync() with FormatListAsync() which instead of inserting the data directly into the ObservableCollection<>, returns a List<>. Then I have a "middle man" function

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
}

I probably could just loop trough mylist and add it one by one into the ObservableCollection<>, but I feel like there surely is a better way.

I think I'm supposed to implement some PropertyChanged event or something like that, but I tried a few (this one for example), unsuccessfully. I don't think I quite understand how to implement it.

rancor1223
  • 356
  • 2
  • 16

1 Answers1

1

If you are assign new value for method parameter then you just change reference's copy to the collection and don't change source reference. You can read more about passing reference types as method parameters on MSDN.

Also, if you will change property that not implements INotifyPropertyChanged itself then you'll have no changes in UI because your view doesn't know about the changes.

In the simple and easy way you can manipulate source collection instead of creating new one. Just do something like

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

The other option, you can implement INotifyPropertyChanged for your ViewModel and raise PropertyChanged event in the setter of Value property:

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

Also, you'll need to assign Value directly in the PopulateListAsync():

public static async Task PopulateListAsync() 
{
    Value = new ObservableCollection<MyClass>(await FormatListAsync());
}
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • I though of the first way of doing things. I was wondering if there is a better way. About the `NotifyPropertyChanged` - can I implement it without using MVVM pattern? This is my first proper project in C# and I honestly gave up on MVVM as I just couldn't get it to work. – rancor1223 Nov 08 '16 at 21:33
  • @rancor1223 well, MVVM is the better way :) Also, you do not need to use `ObservableCollection` if you are changing whole list then your property may have type `List`. Use ObservableCollection if you want manipulate collection dynamically (with clear, add and other methods). Ok, you can implement INPC for your object that is not separated class but that is datasource for your View. Also, there is a really bad way with manipulating your controls and its properties directly: `ObservableCollection data = new ObservableCollection(...); ListBox.ItemsSource = data;` – Vadim Martynov Nov 09 '16 at 07:47
  • I will give MVVM a shot next time. It's just too much for me right now :). And I will see about using just a `List<>`, though was thinking `ObservableCollection<>` gives me the space to expend it later if needed. Thanks a lot for the help! – rancor1223 Nov 09 '16 at 07:57