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

WPF中如何将两个不同类的数据绑定至同一DataGrid

解决WPF DataGrid绑定不同类列表的AC显示与排序问题

方案一:使用值转换器直接处理跨类属性绑定

这种方式无需修改原有类结构,通过转换器判断对象类型并返回对应AC值:

  1. 创建AC值转换器
public class AcValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Player player)
        {
            return player.Ac;
        }
        else if (value is Monster monster)
        {
            return monster.Stats?.Ac ?? 0;
        }
        return 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
  1. 在XAML中引用转换器并修改AC列绑定
    先在窗口/用户控件的资源中声明转换器:
<Window.Resources>
    <local:AcValueConverter x:Key="AcConverter"/>
</Window.Resources>

然后修改DataGrid的AC列:

<DataGridTextColumn Header="AC" Binding="{Binding Converter={StaticResource AcConverter}}"/>

同理,HP列也可以用类似转换器处理(Player无Hp属性时返回N/A):

public class HpValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Monster monster)
        {
            return monster.Hp;
        }
        return "N/A";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

方案二:创建统一ViewModel(推荐,更易维护与排序)

通过包装类统一两个实体的属性,同时直接处理排序逻辑:

  1. 创建统一的CreatureViewModel
public class CreatureViewModel
{
    public string Name { get; set; }
    public int Id { get; set; }
    public int Ac { get; set; }
    public string HpDisplay { get; set; }
    public int Initiative { get; set; } // 用于排序的核心属性

    // 从Player转换
    public static CreatureViewModel FromPlayer(Player player)
    {
        return new CreatureViewModel
        {
            Name = player.Name,
            Id = player.Id,
            Ac = player.Ac,
            HpDisplay = "N/A",
            Initiative = player.InitiativeBonus
        };
    }

    // 从Monster转换
    public static CreatureViewModel FromMonster(Monster monster)
    {
        if (monster.Stats == null) return null;
        
        return new CreatureViewModel
        {
            Name = monster.Name,
            Id = monster.Id,
            Ac = monster.Stats.Ac,
            HpDisplay = $"{monster.Hp}/{monster.Stats.MaxHp}",
            Initiative = (monster.Stats.Dex - 10) / 2 // 计算敏捷 modifier 作为 initiative
        };
    }
}
  1. 后台转换列表并排序
// 假设已有players和monsters两个数据源列表
var creatureViewModels = new List<CreatureViewModel>();
creatureViewModels.AddRange(players.Select(CreatureViewModel.FromPlayer));
creatureViewModels.AddRange(monsters.Select(CreatureViewModel.FromMonster).Where(vm => vm != null));

// 按Initiative从高到低排序
creatureViewModels = creatureViewModels.OrderByDescending(vm => vm.Initiative).ToList();

// 绑定到DataGrid
creatureDatagrid.ItemsSource = creatureViewModels;
  1. 简化XAML绑定
    此时所有列都可以直接绑定统一属性,无需转换器:
<DataGrid x:Name="creatureDatagrid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
        <DataGridTextColumn Header="AC" Binding="{Binding Ac}"/>
        <DataGridTextColumn Header="HP" Binding="{Binding HpDisplay}"/>
    </DataGrid.Columns>
</DataGrid>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:40:53