0

I have a List Box in WPF and I want the content of the list to change everytime the values are changed in code.

At the start of my program I insert the default values in the ListBox and this works well.

using System; using System.Collections.Generic; using System.Linq;
using System.Text; using System.Threading.Tasks; using System.ComponentModel;
using System.Collections.ObjectModel;

public partial class MainWindow : Window
{
    //here is my data which goes into the list
    private DataTable _dataTable1 = null;
    //list which goes into ListBox
    private List<CompareListItem> _compareListItems1 = null;
    public MainWindow()
    {
        InitializeComponent();
        // ..Code missing which writes data in _dataTable
        //ReloadCompareList fills the _compareListItems1 with data from _dataTable1
        _compareListItems1 = ReloadCompareList(_dataTable1);
        //here I do the binding to the ListBox
        compareSelectionList1.ItemsSource = _compareListItems1;
    }

But when I change the values here it does not affect the ListBox

        //this method is called when i want to replace the entire _compareListItems1 list
        private void tableList1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //this method write my data into _dataTable
            _dataTable1 = ReloadTableList(tableList1, _dataTable1, tableGrid1);
            if (_dataTable1 != null)
            {
                //the values of my compare list are replaced, but nothing happens with the ListBox
                _compareListItems1 = ReloadCompareList(_dataTable1);    // ESSENTIAL LINE

            }
        }
}

Each item in my ListBox will be a CompareListItem. I found here on stackoverflow the following topic about INotifyPropertyChanged and I implemented this here. It works when i update a single object in my list.

// Class for the items displayed in the Listbox of the compare list
public class CompareListItem : INotifyPropertyChanged
{
    private string itemTitle;
    public string ItemTitle
    {
        get{return itemTitle;}
        set{
            //this works when a single value in the list is changed, but not if i add or delete someting
            SetField(ref itemTitle, value, "ItemTitle");
        }
    }

    public CompareListItem(string title)    {
        //does not affect the data bindings, could be "itemTitle = title;" to
        SetField(ref itemTitle, title, "ItemTitle");
    }
    //this is from https://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value))
            return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

edit: here the XAML of my ListBox:

<ListBox x:Name="compareSelectionList1" Margin="10,0,10,10" IsSynchronizedWithCurrentItem="False"  Grid.Row="1" Height="100" VerticalAlignment="Bottom" SelectionMode="Multiple">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0,2">
                <TextBlock Text="{Binding ItemTitle, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}"></TextBlock>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

When I add the following line it will work. But I think that is not the meaning of the approach with the DataBindings. I understood the approach like "you mention the view-element once in the code and then you never use the name "compareSelectionList1" again."

_compareListItems1 = ReloadCompareList(_dataTable1);    // ESSENTIAL LINE
compareSelectionList1.ItemsSource = _compareListItems1;

How can I replace my list so that the ListBox will be updated to via the data-binding?

Community
  • 1
  • 1
Marc Trittibach
  • 371
  • 3
  • 8

1 Answers1

2

You're setting _compareListItems1 to a new instance of List<CompareListItem>, but compareSelectionList1.ItemsSource still refers to the previous instance. That's why you need to reassign ItemsSource for it to work.

But I think that is not the meaning of the approach with the DataBindings

Currently, you're not using a binding to set the ItemsSource, so it can't be refreshed automatically. To do that, you need to expose the list as a property, and implement INotifyPropertyChanged in your Window (another option is to expose it as a dependency property). In XAML, bind ItemsSource to the list property, and it will work as expected.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758