1
votes

I recently started to learn the MVVM Pattern and created a simple application to test a few things.

I have a simple View with:

  • ListBox holding ObservableCollection of Items
  • Delete Button
  • New Button
  • TextBox for Item Description
  • TextBox for Item Value

Everything works except for the fact that, if i'm updating the item description the ListBox entry isn't updating. I read some articles about this, so i think it has something to do with CollectionChanged isn't called. I tried some possible solutions to this problem, but none of them worked. So maybe there is something generally wrong with my approach.

Hopefully someone can help me with this problem.

Model/Item.cs

internal class Item : INotifyPropertyChanged
{

    #region Fields 
    private string value;
    private string description;
    #endregion

    #region Constructors
    public Item()
    {
    }

    public Item(string value, string description) {
        this.description = description;
        this.value = value;
    }
    #endregion 

    public String Value
    {
        get
        {
            return value;
        }
        set
        {
            this.value = value;
            OnPropertyChanged("Value");
        }
    }

    public String Description
    {
        get
        {
            return description;
        }
        set
        {
            description = value;
            OnPropertyChanged("Description");
        }
    }

    #region Overrides
    public override string ToString()
    {
        return description;
    }
    #endregion String Override

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }

    }
    #endregion

}

ViewModel/MainViewModel.cs

...

private ObservableCollection<Item> items;
private Item selectedItem;

public ObservableCollection<Item> Items {
    get
    {
        return items;
    }
    set
    {
        items = value;
        OnPropertyChanged("Items");
    }
}
public Item SelectedItem {
    get
    {
        return selectedItem;
    }
    set
    {
        selectedItem = value;
        OnPropertyChanged("SelectedItem");
    }
}

...

View/MainWindow.xaml

...

<Button Content="New" Command="{Binding NewCommand}" />
<Button Content="Delete" Command="{Binding DeleteCommand}" />
<ListBox x:Name="lbxItems" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />
<TextBox Text="{Binding SelectedItem.Description}" />
<TextBox Text="{Binding SelectedItem.Value}" />

...
2
You use both SelectedRange and SelectedItem for the listbox/textbox bindings. Is this intended?Dirk
Could you provide your implementation of Item class?sszarek
Are you calling OnPropertyChanged("Description") when the value in Description property is updated?Bells
Hi Dirk. I tried to simplify my code to post it here. Updated my question. Its all SelectedItem. Thanks for the hint!systrance
Added full implementation of Item class as requested.systrance

2 Answers

2
votes

with this ItemTemplate it should work

    <ListBox Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Value}" Margin="0,0,10,0/>
                    <TextBlock Text="{Binding Path=Description}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
0
votes

How you generate a PropertyChangedEvent in your model class?

try this:

internal class Range : INotifyPropertyChanged
{
    private string _value;

    public string Value
    {
        get { return _value; }
        set 
        {
            if (_value == value) return;
            _value = value;
            OnPropertyChanged("Value");
        }
    }
    //Do same for the Description property
    //Do not forgot implement INotifyPropertyChanged interface here
}

I hope this help you

Oh! After your update it is clearly. You does not use any datatemplate for listbox item, so WPF calls the ToString() method for show item without DT. But when you update any property, WPF does not know about this because object does not changing. Use Datatemplate or try call OnPropertyChanged with empty string.