单元格对齐方式更改后WPF DataGrid文本搜索不起作用

时间:2018-08-17 03:54:16

标签: wpf datagrid

我正在根据论坛中的示例代码来开发DataGrid文本搜索功能。就我而言,没有固定的列,具体取决于SQL查询中的数据。

一切正常,直到我使用AutoGeneratingColumn在后面的代码中更改列的单元格对齐。 (这里创建了一个简单的示例来重现该问题)

Text Search Not Working for Column after Cell Alignment Change

  [<Window.Resources>
        <Style x:Key="CellAlignCenter" TargetType="{x:Type DataGridCell}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <ContentPresenter HorizontalAlignment="Center" />
                        </Grid>                        
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>    

    <Grid>
        <TextBox x:Name="txtSearch"
                 Height="22" Width="80" VerticalAlignment="Top" Margin="10"/>

        <DataGrid x:Name="dgTest" 
                  Height="200" Width="300"
                  local:DataGridTextSearch.SearchValue="{Binding ElementName=txtSearch, Path=Text, UpdateSourceTrigger=PropertyChanged}"
                  AutoGenerateColumns="True"
                  AutoGeneratingColumn="dgTest_AutoGeneratingColumn">
            <DataGrid.Resources>
                <local:SearchValueConverter x:Key="SearchValueConverter" />
                <Style TargetType="{x:Type DataGridCell}">
                    <Setter Property="local:DataGridTextSearch.IsTextMatch">
                        <Setter.Value>
                            <MultiBinding Converter="{StaticResource SearchValueConverter}">
                                <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text" />
                                <Binding RelativeSource="{RelativeSource Self}" Path="(local:DataGridTextSearch.SearchValue)" />
                            </MultiBinding>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>                  
                        <Trigger Property="local:DataGridTextSearch.IsTextMatch" Value="True">
                        <Setter Property="Background" Value="Orange" />
                        <Setter Property="Foreground" Value="Black" />
                    </Trigger>
                    </Style.Triggers>
                </Style>               
            </DataGrid.Resources>    
        </DataGrid>
    </Grid>][2]

后面的代码:

   public static class DataGridTextSearch
    {
        public static readonly DependencyProperty SearchValueProperty = DependencyProperty.RegisterAttached(
                                                "SearchValue",
                                                typeof(string),
                                                typeof(DataGridTextSearch),
                                                new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Inherits));

        public static string GetSearchValue(DependencyObject obj)
        {
            return (string)obj.GetValue(SearchValueProperty);
        }

        public static void SetSearchValue(DependencyObject obj, string value)
        {
            obj.SetValue(SearchValueProperty, value);
        }

        public static readonly DependencyProperty IsTextMatchProperty = DependencyProperty.RegisterAttached(
                                                                        "IsTextMatch",
                                                                        typeof(bool),
                                                                        typeof(DataGridTextSearch),
                                                                        new UIPropertyMetadata(false));

        public static bool GetIsTextMatch(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsTextMatchProperty);
        }

        public static void SetIsTextMatch(DependencyObject obj, bool value)
        {
            obj.SetValue(IsTextMatchProperty, value);
        }
    }

    public class SearchValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string cellText = values[0] == null ? string.Empty : values[0].ToString();
            string searchText = values[1] as string;

            if (!string.IsNullOrEmpty(searchText) && !string.IsNullOrEmpty(cellText))
                return cellText.Trim().ToLower().Contains(searchText.Trim().ToLower());
            else
                return false;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }

    public class User
    {
        public string Name1 { get; set; }

        public string Name2 { get; set; }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<User> users = new List<User>();
            users.Add(new User() { Name1 = "John Doe", Name2 = "John Doe" });
            users.Add(new User() { Name1 = "Jane Doe", Name2 = "Jane Doe" });

            dgTest.ItemsSource = users;
        }

        private void dgTest_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            string headerName = e.Column.Header.ToString();
            Style styleAlignCenter = FindResource("CellAlignCenter") as Style;

            if (headerName == "Name1")
                e.Column.Width = 100;
            else if (headerName == "Name2")
            {
                e.Column.Width = 100;
                e.Column.CellStyle = styleAlignCenter;
            }
        }
    }

当我从“隐藏代码”中更改单元格对齐方式时,就会发生这种情况。
DataGridCell的模板定义中缺少某些内容吗?
感谢帮助和建议。

1 个答案:

答案 0 :(得分:1)

您的代码看起来不错,但是,当您从WPF后面的代码中更改DataGridCell的样式时,也会从旧样式中删除样式元素(设置程序/触发器),因此只需从旧样式中派生新样式,您会没事的。

只需更改XAML文件即可

<Window.Resources>
    <ResourceDictionary>
        <local:SearchValueConverter x:Key="SearchValueConverter" />
        <Style x:Key="DefaultGridCellStyle" TargetType="{x:Type DataGridCell}">
            <Setter Property="local:DataGridTextSearch.IsTextMatch">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource SearchValueConverter}">
                        <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text" />
                        <Binding RelativeSource="{RelativeSource Self}" Path="(local:DataGridTextSearch.SearchValue)" />
                    </MultiBinding>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="local:DataGridTextSearch.IsTextMatch" Value="True">
                    <Setter Property="Background" Value="Orange" />
                    <Setter Property="Foreground" Value="Black" />
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="CellAlignCenter" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DefaultGridCellStyle}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                            <ContentPresenter HorizontalAlignment="Center" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <TextBox x:Name="txtSearch"
             Height="22" Width="80" VerticalAlignment="Top" Margin="10"/>

    <DataGrid x:Name="dgTest" 
              Height="200" Width="300"
              local:DataGridTextSearch.SearchValue="{Binding ElementName=txtSearch, Path=Text, UpdateSourceTrigger=PropertyChanged}"
              AutoGenerateColumns="True"
              AutoGeneratingColumn="dgTest_AutoGeneratingColumn">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DefaultGridCellStyle}">
            </Style>
        </DataGrid.Resources>
    </DataGrid>
</Grid>