【问题标题】:Filter items in VB.net datagrid in WPF在 WPF 中过滤 VB.net 数据网格中的项目
【发布时间】:2013-10-27 04:51:54
【问题描述】:

WPF/VB.net 新手在这里。

我正在尝试过滤数据网格中的行并玩得很开心。

我已经设法创建了一个对象列表并使用 itemsource 属性来获取要填充的数据网格。

现在我有一个复选框,出于参数考虑,我想单击并仅过滤掉与此条件匹配的那些行。

通过下面的代码,我得到了一般的“对象引用未设置为对象的实例”。错误但有点丢失。我相信 VB 专业人士会看到它。

如果可能的话,我宁愿在代码中做更多的事情,而不是 XAML。

这是我的 XAML:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

    <Grid>
        <DataGrid x:Name="displayGrid" HorizontalAlignment="Left" Margin="62,94,0,0" VerticalAlignment="Top" Height="142" Width="360" SelectionChanged="DataGrid_SelectionChanged"/>
        <Button Content="Load" HorizontalAlignment="Left" Margin="62,51,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <CheckBox x:Name="showOnlyChildren" Content="Show Only Children" HorizontalAlignment="Left" Margin="172,51,0,0" VerticalAlignment="Top" Width="147"/>

    </Grid>
</Window>

这是我的代码:

Class MainWindow 

    Class person

        Property name
        Property age

    End Class

    Dim listOfPersons As New List(Of person)
    Private filteredList As CollectionViewSource

    Private Sub DataGrid_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)

    End Sub

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)

        Dim aPerson As New person With {
            .name = "Fred Smith",
            .age = 12}

        listOfPersons.Add(aPerson)

        Dim bPerson As New person With {
         .name = "Tom Jones",
         .age = 50}

        listOfPersons.Add(bPerson)

        displayGrid.ItemsSource = CollectionViewSource.GetDefaultView(listOfPersons)

    End Sub


    Private Sub ShowOnlyChildrenFilter(ByVal sender As Object, ByVal e As FilterEventArgs)
        Dim person As person = TryCast(e.Item, person)
        If person IsNot Nothing Then
            ' Filter out persons with age less than 18
            If person.age < 19 Then
                e.Accepted = True
            Else
                e.Accepted = False
            End If
        End If
    End Sub


    Private Sub AddFiltering(ByVal sender As Object, ByVal args As RoutedEventArgs) Handles showOnlyChildren.Checked
        AddHandler filteredList.Filter, AddressOf ShowOnlyChildrenFilter
    End Sub

    Private Sub RemoveFiltering(ByVal sender As Object, ByVal args As RoutedEventArgs)
        RemoveHandler filteredList.Filter, AddressOf ShowOnlyChildrenFilter
    End Sub




End Class

编辑:好的,但肯定会到达那里。我合并了一些我发现 here 的更改,感谢我来到这里的帮助......这就是代码现在的样子:

Imports System.ComponentModel

Class MainWindow

    Class person

        Property name
        Property age

    End Class

    Dim listOfPersons As New List(Of person)
    Private filteredList As CollectionViewSource
    Dim view As ICollectionView

    Private Sub DataGrid_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)

    End Sub

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)

        Dim aPerson As New person With {
            .name = "Fred Smith",
            .age = 12}

        listOfPersons.Add(aPerson)

        Dim bPerson As New person With {
         .name = "Tom Jones",
         .age = 50}

        listOfPersons.Add(bPerson)

        view = CollectionViewSource.GetDefaultView(listOfPersons)
        displayGrid.ItemsSource = view

    End Sub


    Function ShowOnlyChildrenFilter(ByVal param As Object) As Boolean
        Dim person As person = TryCast(param, person)
        Dim retValue As Boolean

        If person IsNot Nothing Then
            ' Filter out persons with age less than 18
            If person.age < 19 Then
                retValue = True
            Else
                retValue = False
            End If
        End If

        Return retValue

    End Function

    Private Sub showOnlyChildren_Checked(sender As Object, e As RoutedEventArgs) Handles showOnlyChildren.Checked

        If showOnlyChildren.IsChecked = True Then
            view.Filter = New Predicate(Of Object)(AddressOf ShowOnlyChildrenFilter)
        Else
            'what goes here?
        End If

    End Sub
End Class

我唯一缺少的是在未选中复选框时如何刷新数据网格。谢谢大家。我仍然惊讶于这是多么复杂和令人费解,因为我认为这很简单。

【问题讨论】:

  • 哪一行给出了错误?
  • @Steve AddHandler filteredList.Filter, AddressOf ShowOnlyChildrenFilter,当我单击复选框时。我在 CollectionViewSource 前面添加了 New 关键字,现在它没有错误。只是没有做我想做的事。
  • 我在您发布的代码中没有看到您所指的行??
  • @steve 它在 Sub AddFiltering 中
  • 老实说,我不敢相信您必须通过一些 lambda 函数来获取要过滤的数据网格。是故意复杂的吗?

标签: wpf vb.net xaml datagrid


【解决方案1】:

这应该是评论而不是答案,但我无法评论因为没有足够的代表!

您是否尝试过使用

ICollectionView

如果您能够转换,我可以提供一个 C# 示例!

编辑:

我想我会直接加入这个例子,因为它可能会有所帮助

private void cbBlahYear_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        lvwMainBlahFilter();
    }

    private void lvwMainBlahFilter()
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(lvwMainBlah.ItemsSource);

        view.Filter = null;
        view.Filter = new Predicate<object>(FilterBlahByYearID);
        view.SortDescriptions.Add(new SortDescription("Forename", ListSortDirection.Ascending));
    }

    private Boolean FilterBlahByYearID(object obj)
    {
        BlahModel item = obj as BlahModel;
        if (item == null) return false;

        Int32 myID = 0;
        if (cbBlahYear.SelectedItem != null)
        {
            YearModel year = cbBlahYear.SelectedItem as YearModel;
            myID = year.id;
        }

        if (myID == 0) return false;

        if (item.YearID == myID) return true;
        return false;
    }

【讨论】:

  • 看起来很有趣。你有剩下的吗,比如类定义和数据加载器,以及 XAML? VB.net 几乎没有我可能不得不迁移...所有这些花括号都很可怕 :)
  • 好吧,cb 是一个组合框。 lvw 是一个列表视图,而 FilterbyBlah 只是一个函数。改变语法,你应该在那里。
  • 对不起,我是一个完整的新手。这是我的课:class BlahModel { public object Forename { get; set; } public object YearID { get; set; } }
  • 我的代码下面有一些红线。 screenshot
  • 红色是因为您没有 Year 模型。 cbBlahYear 是一个包含年份模型列表的组合框。这部分代码只是从组合框中获取选定的模型,以便您可以引用它的 id 字段
【解决方案2】:

您要查找的变量filteredList

AddHandler filteredList.Filter, AddressOf ShowOnlyChildrenFilter

在这条线上仍然什么都没有。尝试先将其声明为 NEW:

Private filteredList As New CollectionV

【讨论】:

  • 我在 Dim person As person = TryCast(e.Item, person) 行上放了一个断点,但它从未命中它。是因为函数pass吗?
  • 在检查按钮时,您将处理程序添加到过滤列表。过滤器事件,您没有运行过滤器事件。而且,这永远不会触发,因为您永远不会用数据填充 CollectionViewSource。我认为您可能需要设置filteredList = CollectionViewSource.GetDefaultView(listOfPersons),然后设置displayGrid.ItemsSource = filteredList
【解决方案3】:

好的,完成了。在上面的代码上又犯了几个新手错误。所以这是工作版本。勾选一个复选框,它会根据条件进行过滤。

VB代码:

Imports System.ComponentModel

Class MainWindow

    Class person

        Property name
        Property age

    End Class

    Dim listOfPersons As New List(Of person)
    Dim view As ICollectionView

    Private Sub DataGrid_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
        MsgBox("changed")
    End Sub

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)

        Dim aPerson As New person With {
            .name = "Fred Smith",
            .age = 12}

        listOfPersons.Add(aPerson)

        Dim bPerson As New person With {
         .name = "Tom Jones",
         .age = 50}

        listOfPersons.Add(bPerson)

        view = CollectionViewSource.GetDefaultView(listOfPersons)
        displayGrid.ItemsSource = view

    End Sub


    Function ShowOnlyChildrenFilter(ByVal param As Object) As Boolean
        Dim person As person = TryCast(param, person)
        Dim retValue As Boolean

        If person IsNot Nothing Then
            ' Filter out persons with age less than 18
            If person.age < 19 Then
                retValue = True
            Else
                retValue = False
            End If
        End If

        Return retValue

    End Function

    Private Sub showOnlyChildren_Checked(sender As Object, e As RoutedEventArgs) Handles showOnlyChildren.Checked

        If showOnlyChildren.IsChecked = True Then
            view.Filter = New Predicate(Of Object)(AddressOf ShowOnlyChildrenFilter)
        End If


    End Sub

    Private Sub showOnlyChildren_UnChecked(sender As Object, e As RoutedEventArgs) Handles showOnlyChildren.Unchecked

        If showOnlyChildren.IsChecked = False Then
            view.Filter = Nothing
        End If

    End Sub
End Class

使用 XAML:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

    <Grid>
        <DataGrid x:Name="displayGrid" HorizontalAlignment="Left" Margin="62,94,0,0" VerticalAlignment="Top" Height="142" Width="360" SelectionChanged="DataGrid_SelectionChanged"/>
        <Button Content="Load" HorizontalAlignment="Left" Margin="62,51,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <CheckBox x:Name="showOnlyChildren" Content="Show Only Children" HorizontalAlignment="Left" Margin="172,51,0,0" VerticalAlignment="Top" Width="147"/>

    </Grid>
</Window>

【讨论】:

    猜你喜欢
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 2017-12-10
    • 2011-03-16
    相关资源
    最近更新 更多