简体   繁体   中英

Persist or reapply DataGrid.CellStyle after ICollectionView.Refresh()

I'm using a ICollectionView as ItemsSource for a DataGrid . Using a Style , I'm highlighting the cells of my DataGrid that contain a specific SearchString . Simultaneously I'd like to filter the DataGrid to display those lines that contain at least one cell that matches my search.

For the ICollectionView.Filter to effect the displayed data in my DataGrid , I need to call ICollectionView.Refresh() , which apparently clears the style of the cells, because the whole data is reloaded and displayed fresh.

What would be a way to preserve (or re-apply) the style of the cells after a ICollectionView.Refresh() ?

Here is the code I'm using to style the cells:

<DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
        <Style.Triggers>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource ContainsStringToBooleanConverter}">
                        <Binding Path="Content" RelativeSource="{RelativeSource Self}"/>
                        <Binding Path="DataContext.SearchString" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Background" Value="LightGreen" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataGrid.CellStyle>

Here is how I'm filtering the ICollectionView :

ItemView = CollectionViewSource.GetDefaultView(myItemChildren);
ItemView.Filter = ItemViewFilter;

...

private bool ItemViewFilter(object o)
{
    if (String.IsNullOrWhiteSpace(SearchString)) return true;

    var item = (o as Item);
    if (item == null) return true;

    bool result = (item.ItemText.ToLower().Contains(SearchString.ToLower()));

    return result;
}

Refresh() is called every time SearchString is updated:

public string SearchString
{
    get
    {
        return mySearchString;
    }
    set
    {            
        mySearchString = value;
        ItemView.Refresh();
        OnPropertyChanged("SearchString");
    }
}

Edit: After mm8's comment I took a look at my IMultiValueConverter . It seems when the converter is called after a Refresh , none of the cells contain any text. Here is my converter:

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    if (values.Length != 2) return false;
    if (values[0] == null || values[1] == null) return false;

    string text = "";
    if (values[0].GetType() == typeof(TextBlock))
    {
        // The TextBlock never contains any Text after a Refresh
        text = ((TextBlock)values[0]).Text; 
    }

    string search = values[1] as string;

    if (text == null || search == null) return false;
    if (String.IsNullOrWhiteSpace(text) || String.IsNullOrWhiteSpace(search)) return false;

    return text.ToLower().Contains(search.ToLower());
    }

I switched from my "filter & style" approach for highlighting cells and showing only the rows containing such highlighted cells to an style-only approach.

I added an additional DataGrid.RowStyle to hide the rows not containing my search string:

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
        <Style.Triggers>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource ContainsStringToBooleanConverter}">
                        <Binding Path="." RelativeSource="{RelativeSource Self}"/>
                        <Binding Path="DataContext.SearchString" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataGrid.RowStyle>

This works pretty well and I feel like it might even be a little faster than the filter approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM