1

I have a ListView element in WPF as in the following:

    <ListView Grid.Row="6" Margin="10" Name="ObservationsListView" SelectionChanged="ObservationsListView_SelectionChanged_1">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Observation" Width="122" DisplayMemberBinding="{Binding observationStr}" />
                <GridViewColumn Header="Value" Width="122" DisplayMemberBinding="{Binding valueStr}" />
                <GridViewColumn Header="Hidden State" Width="122" DisplayMemberBinding="{Binding stateStr}" />
            </GridView>
        </ListView.View>
    </ListView>

I am binding the following structure to it:

    public struct ObservationStatePair
    {
        public AddressObservationGenerator.Observation observation { get; set; }
        public AddressObservationGenerator.Observation state { get; set; }
        public string observationStr { get; set; }
        public string stateStr { get; set; }
        public string valueStr { get; set; }
    };

I set an array of ObservationStatePair s as the itemsSource of the ListView, which correctly changes its content as I wish. But additionally, I want to modify the "stateStr" field of the currently selected ObservationStatePair item of the ListView's itemsSource as needed. For this purpose, I do the following modification:

        app.currentSequence[ObservationsListView.SelectedIndex].stateStr = selectedState;
        ObservationsListView.ItemsSource = app.currentSequence;

ObservationsListView is my ListView here and currentSequence is the array of ObservationStatePair objects which I want to modify. But this update of the data source is not reflected in UI, the contents of the ListView does not change.

Am I missing something here? What should I do additionally in order to update the ListView's data source?

Ufuk Can Bicici
  • 3,589
  • 4
  • 28
  • 57
  • What you are missing is that your title says that it *does* work... did you not even read your question before you posted it? – Sheridan Sep 05 '14 at 08:36
  • 1. Implement the `INotifyPropertyChanged` interface in your `ObservationStatePair` class. 2. Don't use an array, use an `ObservableCollection`. – Sheridan Sep 05 '14 at 08:37

1 Answers1

2

There are two reasons why it doesn't work:

  • you're not implementing the INotifyPropertyChanged interface, so the binding system cannot detect when a property value has changed

  • ObservationStatePair is a struct, which means it's copied by value. So the view doesn't have a reference to the original object; instead, it has a reference to a boxed copy of the object, so when you modify the original object, the change is not reflected on the one referenced by the view. You should use a class instead.

In general, you should almost always avoid mutable structs, as they are a common source of bugs. See this question for more details: Why are mutable structs evil?


As for why this code doesn't work:

app.currentSequence[ObservationsListView.SelectedIndex].stateStr = selectedState;
ObservationsListView.ItemsSource = app.currentSequence;

Setting the ItemsSource again has no effect, because it's the same array as before (I assume currentSequence is an array, otherwise the first line wouldn't compile). As a workaround, you could set ItemsSource to null, then assign the array to it again. But that's not what I'd recommend; you should make ObservationStatePair and implement INotifyPropertyChanged.

Community
  • 1
  • 1
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • Thanks for the answer. Why setting itemSource to null and reassigning to modified array back to it works and just reassigning doesn't, it did not get it exactly? Becasue that itemsSource keeps referencing the boxed copy of the app.currentSequence and do not refer to the underlying array? – Ufuk Can Bicici Sep 05 '14 at 09:58
  • @UfukCanBiçici, ItemsSource is a dependency property, so it doesn't do anything if you reassign the same value it currently has (in this case, a reference to the currentSequence array). By assigning null before reassigning the array, your cause the value to change, so it will rebind to the array. – Thomas Levesque Sep 05 '14 at 14:32