WPF ListBoxItem loses programmatically styled after scrolling

So, I have a ListBox that is bound to a list of business objects using a DataTemplate:

<DataTemplate x:Key="msgListTemplate">
    <Grid Height="17">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{Binding MaxWidth}" />
            <ColumnDefinition Width="*" />
         </Grid.ColumnDefinitions>
         <TextBlock Grid.Column="0" Foreground="Silver" Text="{Binding SequenceNo}" />
         <TextBlock Grid.Column="1" Text="{Binding MessageName}" />
    </Grid>
</DataTemplate>


<ListBox Name="msgList" 
    Grid.Column="0"
    ItemTemplate="{StaticResource msgListTemplate}"
    SelectionChanged="msgList_SelectionChanged"
    VirtualizingStackPanel.IsVirtualizing="True"
    ScrollViewer.HorizontalScrollBarVisibility="Hidden">
</ListBox>

      

Sometime after binding, I want to tag some items in the list to distinguish them from others. I am doing this on a background thread:

if(someCondition)
{
    msgList.Dispatcher.BeginInvoke(new Fader(FadeListItem), DispatcherPriority.Render, request);
}

delegate void Fader(GMIRequest request);
void FadeListItem(GMIRequest request)
{
    ListBoxItem item =
           msgList.ItemContainerGenerator.ContainerFromItem(request) as ListBoxItem;

    if(item!=null)
            item.Foreground = new SolidColorBrush(Colors.Silver);
}

      

This all works great and some of the list items are greyed out as expected. However, if I scroll so that the gray items no longer appear, then scroll back to where they were, they are no longer silver and are back to the default black leading edge.

Any idea why this is, or how to fix it? Is it because I set IsVirtualizing to true? The list usually contains many items (20,000 is not uncommon).

+1


a source to share


1 answer


Is it because I set IsVirtualizing to true? The list usually contains many items (20,000 is not uncommon).

You nailed it - the element you set for the foreground color gets scatter after the user scrolls.



Even though you have the correct general idea, the way you are going to do this is a very non-WPFy way of doing it - the best way to do it is to have a bool DP in your business object class (or have the BO implement INotifyPropertyChanged ), then bind the bool to the foreground color using a custom IValueConverter that returns (isTrue? whiteBrush: greyBrush).

Since you don't want / cannot modify your business object to support INotifyPropChanged, this is the reason for the MV-VM pattern - create a class that wraps an object that is a DependencyObject and only provides the properties you are interested in displaying.

+3


a source







All Articles