1

I have maximum simple app. I want to fill listbox when button pressed. I use binding, window DataContext is updated after some operation, but UI not updated!

Here is the code:

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Button Content="Button" HorizontalAlignment="Left" Margin="432,288.04,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    <ListBox x:Name="urlsListBox" ItemsSource="{Binding Urls}" HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" VerticalAlignment="Top" Width="417"/>

</Grid>

MainWindow.xaml.cs

    namespace WpfApplication1
{

    public partial class MainWindow : Window
    {
        ViewModel model = new ViewModel();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = model;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            model.GetUrls();
        }
    }
}

ViewModel.cs

    namespace WpfApplication1
{
    class ViewModel
    {
        private ObservableCollection<Url> Urls { get; set; }

        public ViewModel()
        {
            Urls = new ObservableCollection<Url>();
        }

        public void GetUrls()
        {
            for (int i = 0; i < 5; i++)
            {
                Urls.Add(new Url { link = i.ToString() });
            }
        }
    }

    public class Url
    {
        public string link { get; set; }
    }
}
Dom
  • 38,906
  • 12
  • 52
  • 81
BJladu4
  • 263
  • 4
  • 15

2 Answers2

0

You need to support property change notification. Use the NuGet package manager to reference the MVVM Lite project, derive your ViewModel from ViewModelBase and then change your link property to this:

private string _link;
{
    public string link
    {
        get {return this._link;}
        set {this._link=value; RaisePropertyChanged(() => this.link); }
    }
}

You'll also need to do this for your URLs property which needs to be public in order for binding to work. Also I know this is a little bit outside the scope of the question but in general you shouldn't use the Click handler like this, the "proper" way is to add a RelayCommand to your ViewModel and bind your button's Command property to that.

Mark Feldman
  • 15,731
  • 3
  • 31
  • 58
  • `ObservationCollection` already has a `RaisePropertyChanged` event and `CollectionChanged` event. – Dom Dec 15 '13 at 00:58
  • 1
    @Dom true, but that will only give him notification of items added to and removed from the collection. If he wants to change the collection itself or the fields within any of the items then he'll need to implement INotifyPropertyChanged behavior for the other things. Granted, I may have been extending my answer a bit past his specific question, but in my defense I did also mention that he needed to make the collection property public in order for binding to work. – Mark Feldman Dec 15 '13 at 05:23
0

Problem stems from the Urls property within the ViewModel class. You need to make Urls public, otherwise the MainWindow cannot access the property:

ViewModel:

namespace WpfApplication1
{
    public class ViewModel 
    {
        //make this public otherwise MainWindow will not have access to it!
        public ObservableCollection<Url> Urls { get; set; }

        public ViewModel()
        {
            Urls = new ObservableCollection<Url>();
        }

        public void GetUrls()
        {
            for (int i = 0; i < 5; i++)
            {
                Urls.Add(new Url { link = i.ToString() });
            }
        }
}

    public class Url
    {
         public string link { get; set; }
    }

}

Hope this helps and let me know if you have any questions!

Dom
  • 38,906
  • 12
  • 52
  • 81