pirogtm
pirogtm

Reputation: 35

How to fill ListBox from a List with DelegateCommand in WPF?

I faced a problem while trying to fill my ListBox. I have a button in my xaml file:

<Button Content="Show" Command="{Binding ShowSongsBy}" ... >

I also have a ListBox:

<ListBox x:Name="sorted" ItemsSource="{Binding SortedListVM}" ... >

In my ViewModel I have:

        private List<string> _sortedList;
        public List<string> SortedListVM
        {
            set
            {
                _sortedList = value;
                onPropertyChanged();
            }
            get { return _sortedList; }
        }

and

        public event PropertyChangedEventHandler PropertyChanged;

        public void onPropertyChanged([CallerMemberName]string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }

When I press the button, this is what happens (also in ViewModel):

public ICommand ShowSongsBy
        {
            get
            {
                return new DelegateCommand((obj) =>
                {
                    SortedListVM = new List<string>();

                    List<string> testlist = new List<string>();
                    testlist.Add("1");
                    testlist.Add("2");

                    foreach (string i in testlist)
                    {
                        SortedListVM.Add(i);
                    }
                });
            }
        }

What I expect to see in the ListBox: "1" and "2". What I see instead: just "1"

I can't figure out what's the problem. Also if I change the code to this:

public ICommand ShowSongsBy
{
...
                    foreach (string i in testlist)
                    {
                        SortedListVM.Add(i);
                    }

                    SortedListVM.Add("Test1");
...

I see what I expect to see in the ListBox: "1", "2" and "Test1".

What do I do if I only want "1" and "2" to be listed?

My DelegateCommand class:

class DelegateCommand : ICommand
    {
        private Action<object> execute;
        private Func<object, bool> canExecute;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute == null || this.canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            this.execute(parameter);
        }
    }    

Thanks.

Upvotes: 0

Views: 201

Answers (1)

aepot
aepot

Reputation: 4824

Use ObservableCollection instead of List.

private ObservableCollection<string> _sortedList;
public ObservableCollection<string> SortedListVM
{
    get => _sortedList;
    set
    {
        _sortedList = value;
        onPropertyChanged();
    }
}

... and do what you want to do with it. In the same way as you operate with List.

ListBox will dynamically update its layout when you'll make any changes to the collection.

Upvotes: 1

Related Questions