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

WPF MVVM中如何访问TabItem内UserControl的DataGrid并绑定数据

实现方案

1. 定义测试结果数据模型

先创建承载测试结果的实体类,实现INotifyPropertyChanged以便后续属性动态更新:

public class NetworkTestResult : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }

    private string _size;
    public string Size
    {
        get => _size;
        set { _size = value; OnPropertyChanged(); }
    }

    private string _status;
    public string Status
    {
        get => _status;
        set { _status = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 创建Comp_Item的视图模型(CompItemVM)

这个VM对应单个Comp_Item控件的数据源,包含三个ObservableCollection分别绑定三个DataGrid:

public class CompItemVM : INotifyPropertyChanged
{
    // 对应connDataGrid的数据源
    public ObservableCollection<NetworkTestResult> ConnResults { get; } = new ObservableCollection<NetworkTestResult>();
    // 对应outDataGrid的数据源
    public ObservableCollection<NetworkTestResult> OutResults { get; } = new ObservableCollection<NetworkTestResult>();
    // 对应inDataGrid的数据源
    public ObservableCollection<NetworkTestResult> InResults { get; } = new ObservableCollection<NetworkTestResult>();

    // 电脑名称,用于TabItem的Header显示
    private string _computerName;
    public string ComputerName
    {
        get => _computerName;
        set { _computerName = value; OnPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. 绑定Comp_Item.xaml的DataGrid

修改Comp_Item.xaml,将三个DataGrid的ItemsSource绑定到CompItemVM的对应集合:

<UserControl x:Class="YourNamespace.Comp_Item"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             mc:Ignorable="d">
    <Grid>
        <DataGrid x:Name="connDataGrid" ItemsSource="{Binding ConnResults}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="名称" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="大小" Binding="{Binding Size}"/>
                <DataGridTextColumn Header="状态" Binding="{Binding Status}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid x:Name="outDataGrid" ItemsSource="{Binding OutResults}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="名称" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="大小" Binding="{Binding Size}"/>
                <DataGridTextColumn Header="状态" Binding="{Binding Status}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid x:Name="inDataGrid" ItemsSource="{Binding InResults}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="名称" Binding="{Binding Name}"/>
                <DataGridTextColumn Header="大小" Binding="{Binding Size}"/>
                <DataGridTextColumn Header="状态" Binding="{Binding Status}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

4. 构建DashboardVM并关联CompItemVM集合

在DashboardVM中创建CompItemVM的集合,绑定到TabControl,同时实现测试命令:

public class DashboardVM : INotifyPropertyChanged
{
    // 所有电脑的VM集合,绑定到TabControl
    public ObservableCollection<CompItemVM> ComputerItems { get; } = new ObservableCollection<CompItemVM>();

    // 开始测试的命令
    public ICommand StartTestCommand { get; }

    public DashboardVM()
    {
        // 初始化4个电脑的VM
        ComputerItems.Add(new CompItemVM { ComputerName = "Computer1" });
        ComputerItems.Add(new CompItemVM { ComputerName = "Computer2" });
        ComputerItems.Add(new CompItemVM { ComputerName = "Computer3" });
        ComputerItems.Add(new CompItemVM { ComputerName = "Computer4" });

        StartTestCommand = new RelayCommand(ExecuteStartTest);
    }

    private void ExecuteStartTest()
    {
        // 对Computer1执行ping测试,结果添加到对应的集合
        var comp1VM = ComputerItems.FirstOrDefault(vm => vm.ComputerName == "Computer1");
        if (comp1VM != null)
        {
            // 替换为真实ping逻辑
            comp1VM.ConnResults.Add(new NetworkTestResult 
            { 
                Name = "Ethernet", 
                Size = "8 Bytes", 
                Status = "Pass" 
            });
        }

        // 同理可处理其他电脑的测试
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

// 简单实现RelayCommand(无第三方库时使用)
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;

    public void Execute(object parameter) => _execute();

    public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

5. 绑定Dashboard.xaml的TabControl

修改Dashboard.xaml,将TabControl绑定到DashboardVM的ComputerItems集合:

<UserControl x:Class="YourNamespace.Dashboard"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:YourNamespace"
             mc:Ignorable="d">
    <Grid>
        <StackPanel>
            <Button Content="开始测试" Command="{Binding StartTestCommand}" Margin="10"/>
            <TabControl ItemsSource="{Binding ComputerItems}">
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding ComputerName}"/>
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <local:Comp_Item/>
                    </DataTemplate>
                </TabControl.ContentTemplate>
            </TabControl>
        </StackPanel>
    </Grid>
</UserControl>

6. 设置Dashboard的DataContext

在Dashboard构造函数中设置DataContext:

public Dashboard()
{
    InitializeComponent();
    DataContext = new DashboardVM();
}

核心思路说明

  • 完全遵循MVVM:所有数据操作在VM层完成,不直接操作View控件
  • 利用ObservableCollection的自动通知特性,添加数据后UI自动更新
  • 每个Comp_Item对应独立VM,确保不同Tab数据互不干扰
  • 通过集合绑定实现TabControl与多个Comp_Item的关联,避免硬编码TabItem

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:46:08