简体   繁体   English

在ICollectionView.Refresh()之后坚持或重新应用DataGrid.CellStyle

[英]Persist or reapply DataGrid.CellStyle after ICollectionView.Refresh()

I'm using a ICollectionView as ItemsSource for a DataGrid . 我正在使用ICollectionView作为DataGrid ItemsSource Using a Style , I'm highlighting the cells of my DataGrid that contain a specific SearchString . 使用Style ,我突出显示了包含特定SearchString DataGrid单元格。 Simultaneously I'd like to filter the DataGrid to display those lines that contain at least one cell that matches my search. 同时,我想过滤DataGrid以显示那些包含至少一个与我的搜索匹配的单元格的行。

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. 为了使ICollectionView.Filter能够影响DataGrid显示的数据,我需要调用ICollectionView.Refresh() ,这显然清除了单元格的样式,因为整个数据都已重新加载并显示为新的。

What would be a way to preserve (or re-apply) the style of the cells after a ICollectionView.Refresh() ? 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 : 这是我过滤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: 每次更新SearchString都会调用Refresh()

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 . 编辑:在mm8的注释之后,我看了一下IMultiValueConverter It seems when the converter is called after a Refresh , none of the cells contain any text. 似乎在Refresh之后调用转换器时,所有单元格都不包含任何文本。 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来隐藏不包含搜索字符串的行:

<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. 这工作得很好,我觉得它甚至可能比过滤器方法快一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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