Question

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; }
    }
}
Was it helpful?

Solution

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!

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top