tags:

views:

1989

answers:

5

I have a WPF ListBox, and I've added some 'FooBar' objects as items (by code). FooBars aren't WPF objects, just dumb class with an overwritten ToString() function.

Now, when I change a property which influences the ToString, I'd like to get the ListBox to update.

  1. How can I do this 'quick and dirty' (like repaint).
  2. Is dependency properties the way to go on this?
  3. Is it worth it/always advisable, to create a wpf wrapper class for my FooBars?

Thanks...

A: 

If the collection object you use to store the items is an observablecollection<> then this is handled for you.

i.e if the collection is changed any controls databound to it will be updated and vice versa.

Blounty
Well the listbox items IS the collection: myList.Items.Add(new FooBar());
Benjol
+1  A: 

Try implementing the INotifyPropertyChanged interface on your FooBar objects. When they change, raise PropertyChanged events, passing string.Empty as the property name. That should do the trick.

Samuel Jack
Yes, but no. No-one seems to be signed up to my event :(
Benjol
+4  A: 
Drew Noakes
Thanks for the info, I tried what you said in your Edit, but no joy. Elements get added to the listbox, but nothing updates when I fire PropertyChanged - no-one seems to be listening...
Benjol
Do your elements fire the INotifyPropertyChanged event when their properties change? Can you post some sample code in your question?
Drew Noakes
My fault, I just changed the code, not the xaml. I'll try again tomorrow and mark you up!
Benjol
It worked, thank you. I'm just doing a proto GUI at the moment, so I don't need anything more snazzy, but I'm looking at the string formating just in case.
Benjol
+2  A: 

The correct solution here is to use an ObservableCollection<> for your ListBox IetmsSource property. WPF will automatically detect any changes in this collection's contents and force the corresponding ListBox to update to reflect the changes.

You may want to read this MSDN article for more information. It was written to specifically explain how to handle this scenario

http://msdn.microsoft.com/en-us/magazine/dd252944.aspx?pr=blog

JaredPar
I completely agree with you here.
Blounty
A: 

Here is the C# code I have working for this:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace ListboxOfFoobar
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
     public Window1()
     {
      InitializeComponent();
     }

     private void Button_Click(object sender, RoutedEventArgs e)
     {
      ObservableCollection<FooBar> all = (ObservableCollection<FooBar>)FindResource("foobars");
      all[0].P1 = all[0].P1 + "1";
     }
    }
    public class FooBar : INotifyPropertyChanged
    {
     public FooBar(string a1, string a2, string a3, string a4)
     {
      P1 = a1;
      P2 = a2;
      P3 = a3;
      P4 = a4;
     }

     public event PropertyChangedEventHandler PropertyChanged;
     private void NotifyPropertyChanged(String info)
     {
      if (PropertyChanged != null)
      {
       PropertyChanged(this, new PropertyChangedEventArgs(info));
      }
     }

     private String p1;
     public string P1
     {
      get { return p1; }
      set
      {
       if (value != this.p1)
       {
        this.p1 = value;
        NotifyPropertyChanged("P1");
       }
      }
     }
     private String p2;
     public string P2
     {
      get { return p2; }
      set
      {
       if (value != this.p2)
       {
        this.p2 = value;
        NotifyPropertyChanged("P2");
       }
      }
     }
     private String p3;
     public string P3
     {
      get { return p3; }
      set
      {
       if (value != this.p3)
       {
        this.p3 = value;
        NotifyPropertyChanged("P3");
       }
      }
     }
     private String p4;
     public string P4
     {
      get { return p4; }
      set
      {
       if (value != this.p4)
       {
        this.p4 = value;
        NotifyPropertyChanged("P4");
       }
      }
     }
     public string X
     {
      get { return "Foooooo"; }
     }
    }
    public class Foos : ObservableCollection<FooBar>
    {
     public Foos()
     {
      this.Add(new FooBar("a", "b", "c", "d"));
      this.Add(new FooBar("e", "f", "g", "h"));
      this.Add(new FooBar("i", "j", "k", "l"));
      this.Add(new FooBar("m", "n", "o", "p"));
     }
    }
}

Here is the XAML:

<Window x:Class="ListboxOfFoobar.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListboxOfFoobar"
    xmlns:debug="clr-namespace:System.Diagnostics;assembly=System"

    Title="Window1" Height="300" Width="300"        
        >
    <Window.Resources>
        <local:Foos x:Key="foobars" />
        <DataTemplate x:Key="itemTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock MinWidth="80" Text="{Binding Path=P1}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P2}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P3}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P4}"/>
            </StackPanel>
        </DataTemplate>

    </Window.Resources>

    <DockPanel>
        <ListBox DockPanel.Dock="Top"
         ItemsSource="{StaticResource foobars}"
         ItemTemplate="{StaticResource itemTemplate}" Height="229" />
        <Button  Content="Modify FooBar" Click="Button_Click" DockPanel.Dock="Bottom" />
    </DockPanel>
</Window>

Pressing the Button causes the first property of the first FooBar to be updated and for it to show in the ListBox.

hughdbrown