.NET 7 WPF中UserControl与Window间的数据传递问题
解决.NET 7 WPF MVVM数据传递问题方案
1. 定义基础数据模型
先创建带Name属性的列表项模型,实现INotifyPropertyChanged以支持属性变更通知:
using System.ComponentModel; using System.Runtime.CompilerServices; public class ListItem : INotifyPropertyChanged { private string _name; public string Name { get => _name; set { _name = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 重构MainViewModel作为全局数据源中枢
将原始列表、过滤后列表、所有过滤条件统一放在MainViewModel中,实现INotifyPropertyChanged并整合过滤逻辑:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Windows.Input; public class MainViewModel : INotifyPropertyChanged { // 原始数据集 public ObservableCollection<ListItem> OriginalList { get; set; } = new(); // 过滤后的结果集 private ObservableCollection<ListItem> _filteredList; public ObservableCollection<ListItem> FilteredList { get => _filteredList; set { _filteredList = value; OnPropertyChanged(); } } // 子过滤复选框条件 private bool _checkBool1; public bool CheckBool1 { get => _checkBool1; set { _checkBool1 = value; OnPropertyChanged(); ExecuteFilter(); } } private bool _checkBool2; public bool CheckBool2 { get => _checkBool2; set { _checkBool2 = value; OnPropertyChanged(); ExecuteFilter(); } } // 文本框过滤条件 private string _filterText = string.Empty; public string FilterText { get => _filterText; set { _filterText = value; OnPropertyChanged(); ExecuteFilter(); } } // 过滤命令(兼容手动触发场景) public ICommand FilterCommand { get; } // 打开目标Window的命令 public ICommand OpenTargetWindowCommand { get; } public MainViewModel() { // 初始化测试数据 OriginalList.Add(new ListItem { Name = "Item1" }); OriginalList.Add(new ListItem { Name = "Item2" }); OriginalList.Add(new ListItem { Name = "FilteredItem1" }); OriginalList.Add(new ListItem { Name = "FilteredItem2" }); FilteredList = new ObservableCollection<ListItem>(OriginalList); FilterCommand = new RelayCommand(ExecuteFilter); OpenTargetWindowCommand = new RelayCommand(OpenTargetWindow); } // 核心过滤逻辑:整合所有条件生成结果集 private void ExecuteFilter() { var query = OriginalList.AsEnumerable(); // 应用复选框过滤(可根据业务需求调整规则) if (CheckBool1) query = query.Where(item => item.Name.Contains("Filtered")); if (CheckBool2) query = query.Where(item => item.Name.Length > 4); // 应用文本框模糊过滤 if (!string.IsNullOrEmpty(FilterText)) query = query.Where(item => item.Name.Contains(FilterText, System.StringComparison.OrdinalIgnoreCase)); // 更新过滤结果集 FilteredList.Clear(); foreach (var item in query) FilteredList.Add(item); } // 打开目标Window并传递过滤结果 private void OpenTargetWindow() { // 方式1:共享MainViewModel,直接绑定FilteredList var targetWindow = new TargetWindow(); targetWindow.DataContext = this; targetWindow.Show(); // 方式2:传递结果集给独立ViewModel // var targetWindow = new TargetWindow(new TargetWindowViewModel(FilteredList)); // targetWindow.Show(); } public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
3. 调整各UserControl的XAML(取消独立DataContext,绑定全局数据源)
MainWindow XAML(保持原有结构,仅确保DataContext为MainViewModel)
<Window x:Class="MyProject.MainWindow" xmlns:FilterCtrl="clr-namespace:MyProject.FilterControl" xmlns:ListCtrl="clr-namespace:MyProject.ListControl"> <Window.DataContext> <local:MainViewModel/> </Window.DataContext> <Grid> <FilterCtrl:FilterControl Margin="10"/> <ListCtrl:ListControl Margin="10" Grid.Row="1"/> </Grid> </Window>
SubFilter XAML(移除独立DataContext,绑定MainViewModel的复选框属性)
<UserControl x:Class="MyProject.SubFilter"> <Grid> <CheckBox Content="FilterOption1" IsChecked="{Binding CheckBool1}" Margin="5"/> <CheckBox Content="FilterOption2" IsChecked="{Binding CheckBool2}" Margin="5" Grid.Row="1"/> </Grid> </UserControl>
FilterControl XAML(移除独立DataContext,绑定文本框属性和过滤命令)
<UserControl x:Class="MyProject.FilterControl" xmlns:SubFilterCtrl="clr-namespace:MyProject.SubFilterControl"> <Grid> <SubFilterCtrl:SubFilter Margin="5"/> <TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}" Margin="5" Grid.Row="1" Command="{Binding FilterCommand}" PlaceholderText="输入关键词过滤"/> </Grid> </UserControl>
ListControl XAML(移除独立DataContext,绑定过滤后的结果集)
<UserControl x:Class="MyProject.ListControl"> <Grid> <ListView MaxHeight="500" ItemsSource="{Binding FilteredList}" SelectedItem="{Binding SelectedItem}"> <ListView.View> <GridView AllowsColumnReorder="true"> <GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Name" Width="200"/> </GridView> </ListView.View> </ListView> </Grid> </UserControl>
4. 传递过滤结果到其他Window的两种方式
方式1:共享MainViewModel
让目标Window直接使用MainViewModel作为DataContext,XAML中直接绑定FilteredList即可,无需额外数据传递。
方式2:构造函数传递结果集
如果目标Window需要独立ViewModel,可将FilteredList作为参数传入:
// 目标Window的构造函数 public TargetWindow(TargetWindowViewModel viewModel) { InitializeComponent(); DataContext = viewModel; } // 目标Window的ViewModel public class TargetWindowViewModel { public ObservableCollection<ListItem> FilteredList { get; set; } public TargetWindowViewModel(ObservableCollection<ListItem> filteredList) { FilteredList = filteredList; } }
内容的提问来源于stack exchange,提问作者FelixFeuerdorn
相关产品推荐
相关产品推荐

