【问题标题】:How to filter records in a DataGrid?如何过滤 DataGrid 中的记录?
【发布时间】:2017-08-03 16:05:17
【问题描述】:

我正在尝试根据搜索框过滤所选列的数据。到目前为止,我有这个,基于这篇文章:filter wpf datagrid values from a textbox

数据网格集合:

public ICollectionView DataGridCollection
{
   get { return _dataGridCollection; }
   set { _dataGridCollection = value; NotifyPropertyChanged("DataGridCollection"); }
}

过滤器集合:

private void FilterCollection()
{
    if (_dataGridCollection != null)
    {
        _dataGridCollection.Refresh();
    }
}

数据来源:

DataTable pixsellOrders = SqlConnect(query);    
Grid.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate { DataGridCollection = CollectionViewSource.GetDefaultView(pixsellOrders); });
DataGridCollection.Filter = new Predicate<object>(filter);

过滤按钮(右击):

private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        string filter = "";
        FilterBox.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate { filter = FilterBox.Text; });

        if (filter == "")
        {
            Console.WriteLine("no filter");
            return;
        }
        else
        {
            Console.WriteLine(filter);
            FilterCollection();
        }
    }

基于示例:

private bool filter(object item)
    {
        if (item.Subject.Contains(_searchstr) || item.Reference.Contains(searchstr))
        {
            return true;
        }
        return false;
    }

XAML:

<Grid DataContext="{Binding ElementName=ResultsWindow}">
    <DataGrid x:Name="Grid" HorizontalAlignment="Stretch" Height="Auto" Margin="20,45,20,60" VerticalAlignment="Stretch" Width="Auto" ItemsSource="{Binding DataGridCollection}"  >
        <DataGrid.Resources>
            <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
                <MenuItem Header="Filter" Click="MenuItem_Click"/>
            </ContextMenu>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContextMenu"
                Value="{StaticResource DataGridColumnHeaderContextMenu}"/>
            </Style>
        </DataGrid.Resources>
    </DataGrid>
    <Button x:Name="BtnBack" Content="Back" HorizontalAlignment="Right" Margin="0,0,20,20" VerticalAlignment="Bottom" Width="76" Click="BtnBack_Click"/>
    <TextBox Height="27" Margin="65,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="524" Name="FilterBox"/>
    <Label Content="Filter" HorizontalAlignment="Left" Margin="20,10,0,0" VerticalAlignment="Top"/>
</Grid>

在示例中,列在过滤器(私有布尔过滤器)中显式声明。我想仅对选定的列进行过滤(右键单击列标题并从上下文菜单中选择过滤器)。我该如何调整我必须做的事情?不幸的是,我对 XAML 没有太多经验。

【问题讨论】:

    标签: c# wpf search visual-studio-2017 wpfdatagrid


    【解决方案1】:

    过滤DataTable的方法是设置DataViewRowFilter属性:https://msdn.microsoft.com/en-us/library/system.data.dataview.rowfilter(v=vs.110).aspx。这里有一些示例:http://www.csharp-examples.net/dataview-rowfilter/

    您不能使用ICollectionViewFilter 属性过滤DataTable 中的DataView。不支持:

    Why errors when filters DataTable with CollectionView?

    【讨论】:

      【解决方案2】:

      通常,您会在搜索框中使用一些特殊语法实现按列搜索功能,即column:value

      private static bool TryGetValue(string search, out string column, out string value)
      {
          // just an example, should be made more robust
      
          column = null;
      
          value = null;
      
          var match = Regex.Match(search, @"^(\w+):(.*)$");
      
          if (!match.Success)
              return false;
      
          column = match.Groups[1].Value.Trim();
          value = match.Groups[2].Value.Trim();
      
          return true;
      }
      

      例子:

      var strings = new[]
      {
          "column1:abcd",
          "qwerty:asdfg",
          "1234:5678"
      };
      
      foreach (var search in strings)
      {
          string column;
          string value;
      
          if (TryGetValue(search, out column, out value))
          {
              Console.WriteLine($"Column: '{column}'\tValue: '{value}'");
          }
          else
          {
              Console.WriteLine("Invalid syntax");
          }
      }
      

      结果:

      Column: 'column1'       Value: 'abcd'
      Column: 'qwerty'        Value: 'asdfg'
      Column: '1234'  Value: '5678'
      

      这样,用户负责填写该列,您的代码不会被硬编码。

      您可以通过 如果搜索查询中没有前缀列,则意味着搜索所有列

      此外,您可以在该搜索框中实现自动建议。

      等等……

      【讨论】:

      • 用户从不接触该列,这些列是从 SQL 查询中填充的。我希望用户在搜索框中输入一个字符串,然后在该字符串上过滤一列(在该列的所有行中搜索该字符串)。可能是我误解了你的回答
      • 基本上我建议的是一个类似 StackOverflow (stackoverflow.com/help/searching) 上的搜索框,它简单易用/易于实现。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 2023-04-05
      • 2019-09-04
      相关资源
      最近更新 更多