如何对 SQL 中的列表视图进行过滤和分组

How to do both filtering and grouping listview from SQL

如何让我的 listview 同时进行分组和过滤,因为我一次只能让它做一件事。我几乎尝试了所有可能的方法,但 none 的方法奏效了。当我删除

 public string SelectedParam { get { return _selectedParam; } set { _selectedParam = value; OnPropertyChanged("SelectedParam");
        if (_selectedParam == "Krydsmål") { BindData(); } else { hjuldata.ItemsSource = FilterKategori().Tables[0].DefaultView; ; } } }

然后分组有效但过滤无效

我想知道我是否可以使用 sql 来填充而不是填充和过滤,然后让列表视图进行过滤,就像您可以手动添加的项目一样

我的过滤组合框:

 <ComboBox x:Name="Krydsmålbox" Foreground="#FFEAEAEA" Background="#FF303030" FontSize="12" 
Style="{StaticResource ComboBoxTest2}"  ItemTemplate="{StaticResource cmbTemplate2}" 
ItemsSource="{Binding}"  SelectedValuePath="Krydsmålene"
SelectedValue = "{Binding SelectedParam, RelativeSource={RelativeSource FindAncestor, 
                  AncestorType={x:Type Window}},UpdateSourceTrigger=PropertyChanged}" BorderBrush="#FF303030" Height="40" DockPanel.Dock="Top" Margin="586,42,379,0"/>

列表视图

 <ListView x:Name="hjuldata" BorderBrush="#FF303030" Foreground="#FF00FB0B"  ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" Background="#FF303030" ItemsSource="{Binding}" Margin="-160,242,11,22" Grid.ColumnSpan="6" Grid.Row="3" Style="{DynamicResource ListViewStyle2}" DockPanel.Dock="Bottom" Height="576">
 <ListView.View>
 <GridView>
 <GridView.ColumnHeaderContainerStyle>
 <Style TargetType="{x:Type GridViewColumnHeader}">
 <Setter Property="Background" Value="Black" />
 <Setter Property="Foreground" Value="#FFEAEAEA"/>
 <Setter Property="FontWeight" Value="Bold" />
 </Style>
 </GridView.ColumnHeaderContainerStyle>
 <GridViewColumn Header="" >
 <GridViewColumn.CellTemplate>
 <DataTemplate>
 <Image Source="{Binding Billed, Converter={StaticResource nullImageConverter}}" Width="20" Height="20" Stretch="Fill" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,15,0"/>
 </DataTemplate>
 </GridViewColumn.CellTemplate>
 </GridViewColumn>
 <GridViewColumn Header="Model" Width="140" >
 <GridViewColumn.CellTemplate>
 <DataTemplate>
 <TextBlock x:Name="Txt" Text="{Binding Model}" Foreground="#FF00FB0B" />
 </DataTemplate>
 </GridViewColumn.CellTemplate>
 </GridViewColumn>
 <GridViewColumn Header="Årgang" Width="100">
 <GridViewColumn.CellTemplate>
 <DataTemplate>
 <TextBlock x:Name="Txt" Text="{Binding Årgang}" Foreground="#FF00FB0B" />
 </DataTemplate>
 </GridViewColumn.CellTemplate>
 </GridViewColumn>
 <GridViewColumn Header="Motor Type" Width="150" >
 <GridViewColumn.CellTemplate>
 <DataTemplate>
 <TextBlock x:Name="Txt" Text="{Binding [Motor Type]}" Foreground="#FF00FB0B" />
 </DataTemplate>
 </GridViewColumn.CellTemplate>
 </GridViewColumn>
 <GridViewColumn>
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding Krydsmålet}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn>
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding Centerhul}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn Header="ET" Width="auto">
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding ET}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn Header="Bolter" Width="100">
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding Bolter}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn Header="Dæk" Width="300">
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding Dæk}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn Header="Fælge" Width="200">
  <GridViewColumn.CellTemplate>
  <DataTemplate>
  <TextBlock x:Name="Txt" Text="{Binding Fælge}" Foreground="#FF00FB0B" />
  </DataTemplate>
  </GridViewColumn.CellTemplate>
  </GridViewColumn>
  </GridView>
  </ListView.View>

分组方式

  <ListView.GroupStyle>
  <GroupStyle>
  <GroupStyle.ContainerStyle>
  <Style TargetType="{x:Type GroupItem}">
  <Setter Property="Template">
  <Setter.Value>
  <ControlTemplate>
  <Expander IsExpanded="False"  BorderBrush="#FFEAEAEA" BorderThickness="0,0,0,1" >
 <Expander.Header>
 <StackPanel Orientation="Horizontal" DataContext="{Binding Items}">
 <Image Source="{Binding Billed, Converter={StaticResource nullImageConverter}}" Width="20" Height="20" Stretch="Fill" VerticalAlignment="Center"  Margin="0,0,15,0"/>
 <TextBlock  Text="{Binding Mærke}" FontWeight="Bold" Foreground="#FFEAEAEA" FontSize="22" VerticalAlignment="Bottom" />
 <TextBlock Text="{Binding Krydsmålene}"  FontWeight="Bold" Foreground="#FFFBFB00" FontSize="22" VerticalAlignment="Bottom" Margin="0,0,150,0" TextAlignment="Center" />
 </StackPanel>
 </Expander.Header>
 <ItemsPresenter />
 </Expander>
 </ControlTemplate>
 </Setter.Value>
 </Setter>
 </Style>
 </GroupStyle.ContainerStyle>
 </GroupStyle>
 </ListView.GroupStyle>
 </ListView>

CS:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _selectedParam;
    public MainWindow()
    {
        InitializeComponent();
        BindData();
        ICollectionView dataView = CollectionViewSource.GetDefaultView(hjuldata.ItemsSource);
        dataView.GroupDescriptions.Add(new PropertyGroupDescription("Mærke"));

    }

     public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public string SelectedParam { get { return _selectedParam; } set { _selectedParam = value; OnPropertyChanged("SelectedParam");
    if (_selectedParam == "Krydsmål") { BindData(); } else { hjuldata.ItemsSource = FilterKategori().Tables[0].DefaultView; ; } } }

    private void BindData()
    {
        hjuldata.ItemsSource = Kategori().Tables[0].DefaultView;
    }
    public DataSet Kategori()
    {

        Data = @"Select ps.Mærket AS Mærke, P.DataID, P.Billed, P.Model, P.Årgang, P.[Motor Type], P.Krydsmålet, P.Centerhul, P.ET,P.Bolter, P.Dæk, P.Fælge ,PS.Krydsmålene from Data.Hjuldata P  inner join Data.Mærke PS on P.MærkeID = PS.MærkeID ORDER BY ps.Mærket";
        //SQL statement to fetch entries from Hjuldata
        DataSet dsdata = new DataSet();

        //Open SQL Connection
        using (conn = new SqlConnection(connStrings))
        {
            conn.Open();

            //Initialize command object                
            using (cmd = new SqlCommand(Data, conn))
            {                
                SqlDataAdapter adapters = new SqlDataAdapter(cmd);

                //Fill the result set

                adapters.Fill(dsdata);
                conn.Close();
            }
        }
        return dsdata;
    }

    public DataSet FilterKategori()
    {
        Data = @"Select ps.Mærket AS Mærke, P.DataID, P.Billed, P.Model, P.Årgang, P.[Motor Type], P.Krydsmålet, P.Centerhul, P.ET,P.Bolter, P.Dæk, P.Fælge ,PS.Krydsmålene from Data.Hjuldata P  inner join Data.Mærke PS on P.MærkeID = PS.MærkeID WHERE Krydsmålet = @param1";

        //SQL statement to fetch entries from products
        DataSet dsdata = new DataSet();

        //Open SQL Connection
        using (conn = new SqlConnection(connStrings))
        {
            conn.Open();

            //Initialize command object

            using (cmd = new SqlCommand(Data, conn))
            {
                cmd.Parameters.AddWithValue("@param1", SelectedParam);
                SqlDataAdapter adapters = new SqlDataAdapter(cmd);
                //Fill the result set
                adapters.Fill(dsdata);
                conn.Close();
            }
        }  
        return dsdata;
    }

有人可以帮我解决这个问题吗?

我认为您的问题是您使用的是 ADO.NET 数据视图抽象而不是 WPF 数据视图抽象,后者应该更易于使用。在 WPF 中,当您将 collection 或 DataTable 绑定到 ItemsControl 时,会创建一个数据视图 object,它基本上用作 collection 或 DataTable。通过这样做,您可以通过对为此创建的两个不同数据视图进行不同的过滤和分组,将相同的 collection 绑定到多个 ItemsControls 但具有不同的 "views" 数据相同 collection.

在您的情况下,您绑定到 DataTable,这比仅绑定到实现 IList 的 collection 更混乱。对于 DataTable 有一个 DataView class 是 ADO.NET 的一部分,您的 WPF 数据视图基本上将作为一个层,而这个 DataView 更受限制在功能方面(这个 ADO.NET DataView 是您当前在代码中使用的内容)。

无论哪种方式,要获取 WPF 数据视图,您只需要像这样询问 ItemsSource 即可:

ICollectionView dataView = CollectionViewSource.GetDefaultView(myListView.ItemsSource);

现在您需要将 ICollectionView 转换为对设置过滤器和分组更有用的东西。在您的情况下,您有一个 DataTable,因此您需要将其转换为 BindingListCollectionView。不幸的是,这比您为 IListListCollectionView)获得的数据视图更受限制,但是您有一个 DataTable,所以我们现在就使用它(我总是使用 IList 所以我以前从未在生产中实际实现过 DataTable 绑定)。

BindingListCollectionView 没有可操作的 Filter 属性 所以你必须使用它的 CustomFilter 属性 来指定部分 SQL 你想用来过滤你的 collection (基本上你会放在 WHERE 子句中的东西)。就分组而言,我从来没有在 DataTable 绑定上使用过它,但我希望它可以通过在数据视图上更新 GroupDescriptions 来工作。

所以基本上总而言之,我会获取 WPF 数据视图抽象而不是您当前正在使用的 ADO.NET 数据视图抽象,并在其上设置过滤器和分组。此外,我建议只将您的数据作为 IList 引入,或者将其转换为 IList,因为这些在 WPF 中更容易使用。

我认为这是你应该阅读的内容 How to: Group, Sort, and Filter Data in the DataGrid Control

我已经测试过那个,它适用于您的数据结构,您不必对过滤做任何事情,只需更改分组部分和 colectionview