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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:03:19