.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
相关产品推荐
相关产品推荐

