coolercargo
coolercargo

Reputation: 247

ObservableCollection not returning the new data after it is set

When populating an observable collection, I can see that the "return" is not being called when I "set" the new data in the collection. It does work if I set the data from a different location in the program so I must be not understanding some nuance of the way it works. The part that works is when I take out the commented code under "This works", "ChooseFile()" does not. In the debugger I can see the OptionsToChoose has data in both cases. When it works the XAML is updated correctly.

class ScripterViewModel : BindableBase
{

    public ScripterViewModel()
    {
        ScripterModel scripterModel = new ScripterModel();

        ObservableCollection<string> tabsChoice = new ObservableCollection<string>();
        tabsChoice.Add("Tabs");
        tabsChoice.Add("Buttons");
        Tabs = tabsChoice;

        this.OpenFileBtn = new DelegateCommand(chooseFile, canChooseFile).ObservesProperty(() => OpenFile);
        this.SaveFileBtn = new DelegateCommand(saveFile, canSaveFile).ObservesProperty(() => SaveFile);

        //This works
       //var myJSONDoc = JsonConvert.DeserializeObject<JSONclass>(File.ReadAllText(@"C:\Users\mike\Documents\Haas\Scripter\settings.json"));
        //OptionsToChoose = new ObservableCollection<Tabbed>(myJSONDoc.TabbedBtns);

    }
       public void chooseFile()
    {
        var myJSONDoc = JsonConvert.DeserializeObject<JSONclass>(File.ReadAllText(@"C:\Users\mike\Documents\Haas\Scripter\settings.json"));
        OptionsToChoose = new ObservableCollection<Tabbed>(myJSONDoc.TabbedBtns);

    }
        public ObservableCollection<Tabbed> _optionsToChoose = new ObservableCollection<Tabbed>();
        public ObservableCollection<Tabbed> OptionsToChoose
    {
        get
        {
            return _optionsToChoose;
        }
        set
        {
            _optionsToChoose = value;
        }
    }

}

Upvotes: 0

Views: 710

Answers (4)

Dan Siegel
Dan Siegel

Reputation: 5799

As has already been brought up, given your code you would need to make the property for your collection raise PropertyChanged if you were resetting the collection. That said ObservableCollection is really not an ideal collection type to use. What I would recommend is including MvvmHelpers in your project and using the ObservableRangeCollection

public class MyPageViewModel : BindableBase
{
    public MyPageViewModel()
    {
        OptionsToChoose = new ObservableRangeCollection<Tabbed>();
        SomeCommand = new DelegateCommand(OnSomeCommandExecuted);
    }

    public DelegateCommand SomeCommand { get; }

    public ObservableRangeCollection<Tabbed> OptionsToChoose { get; } 

    private void OnSomeCommandExecuted()
    {
        // get some updated data
        IEnumerable<Tabbed> foo = DoFoo();
        OptionsToChoose.ReplaceRange(foo);
    }
}

You get a couple of benefits there. One you're not allocating and deallocating your collection. Also the ObservableRangeCollection updates the full list before raising PropertyChanged or CollectionChanged events this results in few UI notifications and better app performance.

Upvotes: -1

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48600

Ideally, you should not change the whole reference of ObservableCollection after it is binded. Instead clear items in it and then add new items in it.

public ObservableCollection<Tabbed> _optionsToChoose = new ObservableCollection<Tabbed>();
public ObservableCollection<Tabbed> OptionsToChoose
{
    get
    {
        return _optionsToChoose;
    }
}

OptionsToChoose.Clear();
OptionsToChoose.Add(foo);

Upvotes: 0

Janne Matikainen
Janne Matikainen

Reputation: 5121

When you are creating the OptionsToChoose in the constructor it will be initialized when the viewmodel is used by the view.

In the example that is not working, you are just replacing the ObservableCollection with a new one instead clearing it and adding the items. Therefore you need to notify that the property has been changed like V.Leon pointed out in his answer.

Or just clear the existing collection and populate it with the values from the json.

var myJSONDoc = JsonConvert.DeserializeObject<JSONclass>(File.ReadAllText(@"C:\Users\mike\Documents\Haas\Scripter\settings.json"));
OptionsToChoose.Clear();
foreach (var item in myJSONDoc.TabbedBtns)
{
    OptionsToChoose.Add(item);
}

Upvotes: 2

V.Leon
V.Leon

Reputation: 586

You are not raising PropertyChanged event in the setter of OptionsToChoose. You already extend BindableBase, so raising PropertyChanged event can be done by replacing your current OptionsToChoose property implementation with the following:

public ObservableCollection<Tabbed> OptionsToChoose
{
    get
    {
        return _optionsToChoose;
    }
    set
    {
        SetProperty(ref _optionsToChoose, value);
    }
}

See BindableBase.SetProperty Method

Upvotes: 2

Related Questions