You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET WPF MVVM模式下如何使用Dataset并实现过滤

从DataSet生成ObservableCollection并实现MVVM下的数据过滤

一、DataSet转换为ObservableCollection

1. 手动映射实体

先定义继承自你的ModelTemplate的实体类,以客户实体为例:

VB.NET 实体类

Public Class Customer
    Inherits ModelTemplate

    Private _id As Integer
    Public Property Id As Integer
        Get
            Return _id
        End Get
        Set(value As Integer)
            _id = value
            OnPropertyChanged(NameOf(Id))
        End Set
    End Property

    Private _name As String
    Public Property Name As String
        Get
            Return _name
        End Get
        Set(value As String)
            _name = value
            OnPropertyChanged(NameOf(Name))
        End Set
    End Property

    ' 其他属性依此类推
End Class

接着遍历DataSet中的DataRow,转换为实体并填充到ObservableCollection:

VB.NET 转换代码

' 假设你的DataSet名为ds,包含名为"Customers"的DataTable
Dim customersOC As New ObservableCollection(Of Customer)()

For Each row As DataRow In ds.Tables("Customers").Rows
    Dim customer As New Customer()
    customer.Id = If(row.IsNull("Id"), 0, CInt(row("Id")))
    customer.Name = If(row.IsNull("Name"), String.Empty, CStr(row("Name")))
    ' 映射其他字段
    customersOC.Add(customer)
Next

C# 转换代码参考

ObservableCollection<Customer> customersOC = new ObservableCollection<Customer>();
foreach(DataRow row in ds.Tables["Customers"].Rows)
{
    Customer customer = new Customer()
    {
        Id = row.IsNull("Id") ? 0 : (int)row["Id"],
        Name = row.IsNull("Name") ? string.Empty : (string)row["Name"]
    };
    customersOC.Add(customer);
}

2. 自动映射(可选)

如果DataSet字段较多,可以用AutoMapper这类工具简化映射:

VB.NET 配置示例

' 初始化映射配置
Mapper.Initialize(Sub(cfg)
                      cfg.CreateMap(Of DataRow, Customer)()
                  End Sub)

' 批量转换
Dim customersOC As New ObservableCollection(Of Customer)(
    Mapper.Map(Of IEnumerable(Of Customer))(ds.Tables("Customers").Rows)
)

二、MVVM下实现数据过滤

在MVVM架构中,推荐使用ICollectionView实现过滤,避免直接修改ObservableCollection,保持数据与视图分离。

1. ViewModel中配置ICollectionView

在ViewModel中维护ObservableCollection作为数据源,同时创建对应的ICollectionView用于过滤:

VB.NET ViewModel示例

Public Class CustomerViewModel
    Inherits ModelTemplate

    Private _customers As ObservableCollection(Of Customer)
    Public Property Customers As ObservableCollection(Of Customer)
        Get
            Return _customers
        End Get
        Set(value As ObservableCollection(Of Customer))
            _customers = value
            OnPropertyChanged(NameOf(Customers))
            ' 初始化视图
            CustomerView = CollectionViewSource.GetDefaultView(_customers)
            CustomerView.Filter = AddressOf FilterCustomer
        End Set
    End Property

    Private _customerView As ICollectionView
    Public Property CustomerView As ICollectionView
        Get
            Return _customerView
        End Get
        Set(value As ICollectionView)
            _customerView = value
            OnPropertyChanged(NameOf(CustomerView))
        End Set
    End Property

    Private _filterText As String
    Public Property FilterText As String
        Get
            Return _filterText
        End Get
        Set(value As String)
            _filterText = value
            OnPropertyChanged(NameOf(FilterText))
            ' 过滤条件变化时刷新视图
            CustomerView?.Refresh()
        End Set
    End Property

    ' 过滤逻辑方法
    Private Function FilterCustomer(item As Object) As Boolean
        Dim customer = TryCast(item, Customer)
        If customer Is Nothing Then Return False
        If String.IsNullOrEmpty(FilterText) Then Return True
        ' 按名称模糊过滤,可根据需求修改
        Return customer.Name.IndexOf(FilterText, StringComparison.OrdinalIgnoreCase) >= 0
    End Function

    ' 构造函数中初始化数据源(替换为你的DataSet转换逻辑)
    Public Sub New()
        ' 假设这里调用DataSet转换代码得到customersOC
        Customers = customersOC
    End Sub
End Class

C# ViewModel参考

public class CustomerViewModel : ModelTemplate
{
    private ObservableCollection<Customer> _customers;
    public ObservableCollection<Customer> Customers
    {
        get => _customers;
        set
        {
            _customers = value;
            OnPropertyChanged(nameof(Customers));
            CustomerView = CollectionViewSource.GetDefaultView(_customers);
            CustomerView.Filter = FilterCustomer;
        }
    }

    private ICollectionView _customerView;
    public ICollectionView CustomerView
    {
        get => _customerView;
        set
        {
            _customerView = value;
            OnPropertyChanged(nameof(CustomerView));
        }
    }

    private string _filterText;
    public string FilterText
    {
        get => _filterText;
        set
        {
            _filterText = value;
            OnPropertyChanged(nameof(FilterText));
            CustomerView?.Refresh();
        }
    }

    private bool FilterCustomer(object item)
    {
        var customer = item as Customer;
        if (customer == null) return false;
        if (string.IsNullOrEmpty(FilterText)) return true;
        return customer.Name.IndexOf(FilterText, StringComparison.OrdinalIgnoreCase) >= 0;
    }

    public CustomerViewModel()
    {
        // 初始化Customers
        Customers = GetCustomersFromDataSet();
    }
}

2. 视图绑定

在XAML中绑定视图到ICollectionView,过滤输入框绑定到FilterText:

<Window.DataContext>
    <local:CustomerViewModel />
</Window.DataContext>

<StackPanel>
    <TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}" 
             PlaceholderText="输入名称过滤"/>
    <ListView ItemsSource="{Binding CustomerView}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"/>
                <GridViewColumn Header="名称" DisplayMemberBinding="{Binding Name}"/>
            </GridView>
        </ListView.View>
    </ListView>
</StackPanel>

关键说明

  • 不要直接修改ObservableCollection来实现过滤,ICollectionView是WPF专门为视图层提供的筛选、排序、分组工具,符合MVVM分离原则。
  • UpdateSourceTrigger=PropertyChanged确保输入框内容变化时立即触发过滤。
  • 过滤逻辑可以根据需求扩展,比如多条件组合过滤,只需修改FilterCustomer方法即可。

内容的提问来源于stack exchange,提问作者brobro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 14:18:33