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

WinUI中TabView新增TabItem并传递行数据的实现方案

问题描述

我是C#和WinUI新手,开发的应用中有一个包含固定TabItem的TabView,该固定TabItem内有一个SfDataGrid。双击DataGrid的任意行时会新建一个TabItem,现需根据双击的行填充新TabItem的内容,且切换标签时不能重新加载数据(避免覆盖已编辑内容)。目前找到的动态填充方案会覆盖之前的编辑内容,求具体实现方法。

现有代码

Tasks.xaml(包含TabView和SfDataGrid)

<TabView x:Name="Tabs" AddTabButtonClick="TabView_AddButtonClick" 
         TabCloseRequested="TabView_TabCloseRequested" Loaded="TabView_Loaded" 
         TabDroppedOutside="TabView_TabDroppedOutside" CanDragTabs="True">
    <TabViewItem Header="Tasks" IsClosable="False">
        <TabViewItem.IconSource>
            <SymbolIconSource Symbol="Home" />
        </TabViewItem.IconSource>
        <Grid>
            <Grid>
                <DataGrid:SfDataGrid x:Name="DataGrid"
                        AutoGenerateColumns="False" ItemsSource="{Binding}" 
                        ShowSortNumbers="True" AllowResizingColumns="True" AllowDraggingColumns="True" 
                        SelectionUnit="Row" CellDoubleTapped="DataGrid_CellDoubleTapped" 
                        AllowGrouping="True" ShowGroupDropArea="True" 
                        AllowFiltering="True" FilterRowPosition="FixedTop">
                    <DataGrid:SfDataGrid.Columns>
                        <DataGrid:GridNumericColumn MappingName="ColumnId" HeaderText="ID" ColumnWidthMode="Auto" IsHidden="True"/>
                        <DataGrid:GridNumericColumn MappingName="ColumnStatus" HeaderText="STATUS" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnTaskNr" HeaderText="NR" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnCustomerName" HeaderText="KUND" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnCustomT2" HeaderText="GÄLLER" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnTask" HeaderText="UPPDRAG" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridDateColumn MappingName="ColumnCreatedDate" HeaderText="SKAPAT TIDPUNKT" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True" FilterRowEditorType="Date"/>
                        <DataGrid:GridNumericColumn MappingName="ColumnPriority" HeaderText="PRIORITET" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnCustomT1" HeaderText="ATT GÖRA" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                        <DataGrid:GridTextColumn MappingName="ColumnCustomerRef" HeaderText="KONTAKTPERSON" ColumnWidthMode="Auto" ImmediateUpdateColumnFilter="True"/>
                    </DataGrid:SfDataGrid.Columns>
                </DataGrid:SfDataGrid>
            </Grid>
        </Grid>
    </TabViewItem>
</TabView>

Tasks.xaml.cs(创建新标签的函数)

private void DataGrid_CellDoubleTapped(object sender, Syncfusion.UI.Xaml.DataGrid.GridCellDoubleTappedEventArgs e)
{
    this.DataGrid.SelectedIndex = this.DataGrid.ResolveToRecordIndex(e.RowColumnIndex.RowIndex);


    int rowIndex = e.RowColumnIndex.RowIndex;
    int columnIndex = this.DataGrid.ResolveToGridVisibleColumnIndex(e.RowColumnIndex.ColumnIndex);
    var recordIndex = this.DataGrid.ResolveToRecordIndex(rowIndex);
    var record1 = this.DataGrid.View.Records.GetItemAt(recordIndex);
    var mappingName = this.DataGrid.Columns[columnIndex].MappingName;

    string TaskNr = record1.GetType().GetRuntimeProperty("ColumnTaskNr").GetValue(record1).ToString();

    TabViewItem newItem = new TabViewItem();

    newItem.Header = $"{TaskNr}";
    newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Document };

    Frame frame = new Frame();
    frame.Navigate(typeof(TaskDetails));

    newItem.Content = frame;

    Tabs.TabItems.Add(newItem);
}
解决方案

核心思路是缓存页面实例+复用已打开标签,确保切换标签时不会重建页面、覆盖编辑内容。

1. 修改标签创建逻辑(Tasks.xaml.cs)

加入已存在标签检查,启用页面导航缓存,并传递选中的任务数据:

private void DataGrid_CellDoubleTapped(object sender, Syncfusion.UI.Xaml.DataGrid.GridCellDoubleTappedEventArgs e)
{
    // 获取双击行对应的任务记录
    var recordIndex = DataGrid.ResolveToRecordIndex(e.RowColumnIndex.RowIndex);
    var selectedTask = DataGrid.View.Records.GetItemAt(recordIndex);
    string taskNr = selectedTask.GetType().GetRuntimeProperty("ColumnTaskNr").GetValue(selectedTask).ToString();

    // 检查是否已打开该任务的标签页,避免重复创建
    var existingTab = Tabs.TabItems.OfType<TabViewItem>()
        .FirstOrDefault(tab => tab.Header.ToString() == taskNr);
    
    if (existingTab != null)
    {
        // 直接切换到已存在的标签
        Tabs.SelectedItem = existingTab;
        return;
    }

    // 创建新标签页
    var newTab = new TabViewItem
    {
        Header = taskNr,
        IconSource = new SymbolIconSource { Symbol = Symbol.Document },
        IsClosable = true
    };

    // 创建Frame并启用导航缓存,防止页面重建
    var contentFrame = new Frame();
    contentFrame.NavigationCacheMode = NavigationCacheMode.Required;
    // 导航时传递选中的任务数据
    contentFrame.Navigate(typeof(TaskDetails), selectedTask);

    newTab.Content = contentFrame;
    Tabs.TabItems.Add(newTab);
    Tabs.SelectedItem = newTab;
}

2. 修改TaskDetails页面(TaskDetails.xaml.cs)

只在首次导航时绑定数据,保留编辑状态:

public sealed partial class TaskDetails : Page
{
    private object _taskData; // 保存任务数据引用,避免重复赋值覆盖编辑内容

    public TaskDetails()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        // 仅在首次进入页面时赋值,后续切换回来不再重新绑定
        if (_taskData == null && e.Parameter != null)
        {
            _taskData = e.Parameter;
            DataContext = _taskData;
        }
    }
}

关键说明

  • 导航缓存:NavigationCacheMode.Required让Frame保留页面实例,切换标签时不会重新创建TaskDetails,自然不会覆盖已编辑内容。
  • 标签复用:提前检查是否已打开对应任务的标签,避免重复创建,同时提升操作效率。
  • 数据保留:TaskDetails页面持有任务数据的引用,绑定后编辑的是同一个对象(如果需要独立编辑副本,可以在传递数据时克隆对象,比如手动复制属性或使用对象映射工具)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:16:04