【问题标题】:Persist or reapply DataGrid.CellStyle after ICollectionView.Refresh()在 ICollectionView.Refresh() 之后保留或重新应用 DataGrid.CellStyle
【发布时间】:2017-08-28 06:33:14
【问题描述】:

我将ICollectionView 用作ItemsSource 用于DataGrid。使用Style,我突出显示了我的DataGrid 中包含特定SearchString 的单元格。同时,我想过滤 DataGrid 以显示至少包含一个与我的搜索匹配的单元格的行。

为了使ICollectionView.Filter 影响我DataGrid 中显示的数据,我需要调用ICollectionView.Refresh(),这显然会清除单元格的样式,因为整个数据会重新加载并重新显示。

ICollectionView.Refresh() 之后保留(或重新应用)单元格样式的方法是什么?

这是我用来设置单元格样式的代码:

<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>

这是我过滤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;
}

每次SearchString 更新时都会调用Refresh()

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

编辑: 在 mm8 发表评论后,我查看了我的 IMultiValueConverter。在Refresh 之后调用转换器时,似乎没有任何单元格包含任何文本。这是我的转换器:

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());
    }

【问题讨论】:

  • 调用 Refresh() 后转换器的 Convert 方法是否被命中?
  • 是的,IMultiValueConverter.Convert()Refresh() 之后调用
  • 但它不返回true?那么这意味着你的转换逻辑有问题。只有当 Convert 方法返回 true 时才会设置单元格的背景。
  • 感谢您为我指明方向。刷新后调用转换器时,单元格似乎从不包含任何文本...

标签: c# wpf xaml datagrid styles


【解决方案1】:

我从用于突出显示单元格并仅显示包含此类突出显示单元格的行的“过滤器和样式”方法切换到仅样式方法。

我添加了一个额外的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>

这很好用,我觉得它甚至可能比过滤方法快一点。

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多