Mattias Cibien
Mattias Cibien

Reputation: 296

Listbox bound to an ObservableCollection doesn't update

I am using a ObservableCollection to store the Environment Variables of Windows.

class VariableVieWModel
{
    ObservableCollection<VariableModel> vars;

    public ObservableCollection<VariableModel> Variables
    {
        get
        {
            return vars;
        }
        set
        {
            vars = value;
        }
    }

    public VariableViewModel() 
    {
        Reload();
    }

    public void Reload()
    {
    // Code to retrieve vars
    }
}

This ObservableCollection is bound to a ListBox.

I have added a button in the GUI to reload the Variables whichi, on click, it calls the Reload() procedure.

ListBox content, however, does not change and I cannot add anymore items to the list afer calling Reload().

Under the constructor everything is working fine.

ListBox XAML :

<ListBox x:Name="lbVariables" Grid.Column="0" Margin="0,0,5,0" ItemsSource="{Binding Source={StaticResource variablesViewModel}, Path=Variables}" IsSynchronizedWithCurrentItem="True"> 

I tried using also PropertyChanged as UpdateSource trigger and set most of the Modes.

public void Reload()
    {
        vars = new ObservableCollection<VariableModel>();

        RegistryKey systemVarKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment");

        string[] systemVars = systemVarKey.GetValueNames();

        foreach (string var in systemVars)
        {
            vars.Add(new VariableModel()
            {
                Name = var,
                Values = (systemVarKey.GetValue(var, null, RegistryValueOptions.DoNotExpandEnvironmentNames) as string).Split(';').ToList<string>(),
                Target = EnvironmentVariableTarget.Machine
            });
        } 
        systemVarKey.Close();

        RegistryKey userVarKey = Registry.CurrentUser.OpenSubKey(@"Environment");

        string[] userVars = userVarKey.GetValueNames();

        foreach (string var in userVars)
        {
            vars.Add(new VariableModel()
            {
                Name = var,
                Values = (userVarKey.GetValue(var, null, RegistryValueOptions.DoNotExpandEnvironmentNames) as string).Split(';').ToList<string>(),
                Target = EnvironmentVariableTarget.User
            });
        }
        userVarKey.Close();
    }

Upvotes: 3

Views: 3284

Answers (3)

Rohit Vats
Rohit Vats

Reputation: 81313

You need to implement INotifyPropertyChanged for your VariableVieWModel to refresh your target object bindings. You just have to do this way -

class VariableVieWModel : INotifyPropertyChanged
    { .
      .
            public ObservableCollection<VariableModel> Variables
            {
               get
               {
                  return vars;
               }
               set
               {
                  if(vars!=value)
                  {
                      vars = value;
                      OnPropertyChanged("Variables");
                  }
               }
            }

            public event PropertyChangedEventHandler PropertyChanged;      
            protected void OnPropertyChanged(string name)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            } 
    }

Upvotes: 3

to StackOverflow
to StackOverflow

Reputation: 124794

You haven't modified the ObservableCollection, only replaced it. You should implement INotifyPropertyChanged and call PropertyChanged in the Variables property setter.

BTW it's common in MVVM implementations to have a base class for your ViewModel:

class VariableViewModel : ViewModelBase

and implement common functionality such as INotifyPropertyChanged in the base class to avoid duplication of code.

Upvotes: 3

HCL
HCL

Reputation: 36815

The problem is, that probably your VariableModel does not implement INotifyPropertyChanged. Through ObservableCollection, only changes to the collection are reported, not changes of the contained objects.

Here you will find some implementation possibilities.

Upvotes: 2

Related Questions