views:

414

answers:

3

Is there any way, how to force ObservableCollection to fire CollectionChanged?

I have a ObservableCollection of objects ListBox item source, so every time I add/remove item to collection, ListBox changes accordingly, but when I change properties of some objects in collection, ListBox still renders the old values.

Even if I do modify some properties and then add/remove object to the collection, nothing happens, I still see old values.

Is there any other way around to do this? I found interface INotifyPropertyChanged, but I don't know how to use it.

+1  A: 

Modifying properties on the items in your collection won't fire NotifyCollectionChanged on the collection itself - it hasn't changed the collection, after all.

You're on the right track with INotifyPropertyChanged. You'll need to implement that interface on the class that your list contains. So if your collection is ObservableCollection<Foo>, make sure your Foo class implements INotifyPropertyChanged.

Matt Hamilton
+3  A: 

Hi,
I agree with Matt's comments above. Here's a small piece of code to show how to implement the INotifyPropertyChanged.

===========
Code-behind
===========

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;

namespace WpfApplication1
{   
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        Nicknames names;

        public Window1()
        {
            InitializeComponent();
            this.addButton.Click += addButton_Click;
            this.names = new Nicknames();
            dockPanel.DataContext = this.names;
        }

        void addButton_Click(object sender, RoutedEventArgs e)
        {
            this.names.Add(new Nickname(myName.Text, myNick.Text));
        }
}
public class Nicknames : System.Collections.ObjectModel.ObservableCollection<Nickname> { }

public class Nickname : System.ComponentModel.INotifyPropertyChanged
{
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    void Notify(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propName));
        }
    }

    string name;
    public string Name
    {
        get { return name; }
        set
        {
            name = value;
            Notify("Name");
        }
    }
    string nick;
    public string Nick
    {
        get { return nick; }
        set
        {
            nick = value;
            Notify("Nick");
        }
    }
    public Nickname() : this("name", "nick") { }
    public Nickname(string name, string nick)
    {
        this.name = name;
        this.nick = nick;
    }

    public override string ToString()
    {
        return Name.ToString() + " " + Nick.ToString();
    }
  }
}

XAML

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <DockPanel x:Name="dockPanel">
        <TextBlock DockPanel.Dock="Top">
        <TextBlock VerticalAlignment="Center">Name: </TextBlock>
        <TextBox Text="{Binding Path=Name}" Name="myName" />
        <TextBlock VerticalAlignment="Center">Nick: </TextBlock>
        <TextBox Text="{Binding Path=Nick}" Name="myNick" />
        </TextBlock>
        <Button DockPanel.Dock="Bottom" x:Name="addButton">Add</Button>
        <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" />
    </DockPanel>
</Grid>

Anand
wow, nice example, that's exactly what i needed :)
Darth
Glad I could help :)
Anand
A: 

Thanks... very usefull! :o)

kahr