0
votes

I'm having difficulties on updating a listbox with a change in the list it is bound to.
The main window has the datacontext set through code-behind:

public partial class MainWindow : Window
{
    private ConfigurationListViewModel _ConfListVM;
    public MainWindow()
    {
        _ConfListVM = new ConfigurationListViewModel();
        InitializeComponent();
        DataContext = _ConfListVM.ConfList;
        this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        ConfigMng.CreatedConfigurationEvent += new EventHandler(OnCreateConfiguration);
    }

    void OnCreateConfiguration(object sender, EventArgs e)
    {
        _ConfListVM.Add("Test");
    }

}



public class ConfigurationListViewModel
{
    public ConfigurationList ConfList = new ConfigurationList();
}

public class ConfigurationList : INotifyPropertyChanged
{
    private ObservableCollection<Configuration> _ObservableConfList = new ObservableCollection<Configuration>();
    public ObservableCollection<Configuration> ObservableConfList { get { return _ObservableConfList; } set { _ObservableConfList = value; } }

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


    public ConfigurationList()
    {
        ObservableConfList.Add(new Configuration("aaa"));
        ObservableConfList.Add(new Configuration("bbd"));
    }


    public void Add(Configuration Conf)
    {
        ObservableConfList.Add(Conf);
        OnPropertyChanged(Conf.ConfName);
    }
}

}

In the Main Window XAML I set the User Control:

<GroupBox Header="Configurations" >
    <local:ConfigurationMng x:Name="ConfigMng"/>
</GroupBox>

And in the ConfigurationMng I have the following ListBox, that I bound to the list ConfList

<ListBox Name="lbConfigurationList" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

I can see correctly in the ListBox the 2 element I created with the constructor, but when I manually add another element, PropertyChanged is always null.

I think I understood that I have to set a DataContext (but I thought that if not manually specified, it should use its parent one);

I tried then to set it manually:

<ListBox Name="lbConfigurationList" DataContext="{Binding [??????], RelativeSource={RelativeSource AncestorType={x:Type Window}}}" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

but I got stuck on understanding on what should I bind it. Am I now in MainWindow's datacontext? So i'm in the scope _ConfList.ConfList? I should write just Binding and I should be in the correct DataContext, right?

Nope, even the manually added Configurations disappear.

What am I missing here?

Edit: ConfigurationMng's CodeBehind:

public partial class ConfigurationMng : UserControl
{
    public event EventHandler CreatedConfigurationEvent;

    public ConfigurationMng()
    {
        InitializeComponent();
    }

    private void AddConfiguration(object sender, RoutedEventArgs e) //Called with a button pression
    {
        if (this.CreatedConfigurationEvent != null)
        {
            this.CreatedConfigurationEvent(sender, e);
        }
    }
}

Solved, the problem seems that the main ConfigurationListViewModel wasn't implementing the INotifyPropertyChanged interface, so he just wasn't notifying the listbox of the change. I can't write the actual solution since I rewrote this part of the project

1

1 Answers

0
votes

You are correct that it will inherit the parent's DataContext.

<ListBox Name="lbConfigurationList" DataContext="{Binding [??????], RelativeSource={RelativeSource AncestorType={x:Type Window}}}" ItemsSource="{Binding ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}">

Since your assumption that parent datacontext is inherited, you don't need to explicitly set the DataContext for ListBox. You just need to make sure that your ItemsSource is defined like this

ItemsSource="{Binding ConfList.ObservableConfList, UpdateSourceTrigger=PropertyChanged, diag:PresentationTraceSources.TraceLevel=High}"

You are binding to an ObservableCollection which you don't need INotifyPropertyChanged in your ViewModel because the collection alreay takes care of that. If you want to handle the added/deleted elements then you can use the CollectionChanged of the collection.

Also, your Model Configuration should implement INotifyPropertyChanged if you would want to listen on each item.

From what I can see, your architecture is adding more complexity. Why did you need to create a separate class just to have an ObservableCollection? You can just put it in the ViewModel and leave your Configuration as your model.