Search code examples
c#wpfdatatrigger

WPF DataTrigger only working 1 time


I'm trying out WPF and I have an application with an ObservableCollection hooked up to a ListView. It adds the items perfectly and everything is falling together. It is taking in data from a live source and so item values are getting updated and rows are getting added. But now I want the most recent rows to be highlighted, text changed, something to show that this certain row is being changed. So I set up a data trigger and added a value to the DataType in the ObservableCollection called RecentlyChanged. If its true, then set the text to red, otherwise text is black.

When I run this code the list items change to red and then never change back and I have tried everything and it is ticking me off. I've checked the debugger to and even when the value is no (I'm using strings yes and no because i wanted to try all sorts of data types) it stays red. Code for the data trigger is below:

--Edit: Added in the second datatrigger that i tried using before to no avail.

<ListView ItemsSource="{Binding DataTable, UpdateSourceTrigger=PropertyChanged}">
    <ListView.Resources>
        <Style TargetType="ListViewItem">
            <Setter Property="Foreground" Value="Black"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=RecentlyChanged}" Value="yes">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=RecentlyChanged}" Value="no">
                    <Setter Property="Foreground" Value="Black" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListView.Resources>

Solution

  • The issue is that the ObservableCollection only reports changes to the collection itself, in other words, it fires a CollectionChanged event whenever items are added or removed, but not when properties of those items change. In order to achieve the desired result - updating a data trigger when an item's property changes - the item itself must implement the INotifyPropertyChanged interface and fire the PropertyChanged event when the desired property is set.

    In this case, you can use the following:

    using System.ComponentModel;
    
    public class ListViewItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged(string name)
        {
            var propChanged = PropertyChanged;
            if(propChanged != null)
            {
                propChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    
        private string recentlyChanged = "yes"; // Recently changed on creation
        public string RecentlyChanged
        {
            get { return recentlyChanged; }
            set {
                recentlyChanged = value;
                OnPropertyChanged("RecentlyChanged");
            }
        }
    
        // ... define the rest of the class as usual
    
    }
    

    WPF magic should take care of the rest.