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

如何在WPF中实现自定义DataGrid以展示玩家与怪物信息?

WPF实现动态玩家/怪物信息表格方案

WPF完全可以实现你要求的所有功能,无需更换前端框架。以下是针对你的需求的具体实现方案:

一、数据结构与实时更新基础

  1. 定义统一的实体基类(或ViewModel),让Player和Monster继承它,包含共同属性(如INIT、Name等),同时各自扩展专属属性:
public class CombatEntity : INotifyPropertyChanged
{
    private int _init;
    public int INIT
    {
        get => _init;
        set { _init = value; OnPropertyChanged(); }
    }

    public string Name { get; set; }
    // 其他共同属性...

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

public class Player : CombatEntity
{
    public List<NameValuePair> PlayerAttributes { get; set; }
    public string[] Skills { get; set; }
    // 玩家专属属性...
}

public class Monster : CombatEntity
{
    public List<NameValuePair> MonsterStats { get; set; }
    public string[] Abilities { get; set; }
    // 怪物专属属性...
}
  1. 使用ObservableCollection<CombatEntity>存储所有实体,支持动态增删:
public ObservableCollection<CombatEntity> CombatEntities { get; } = new ObservableCollection<CombatEntity>();

// 添加示例数据
public void AddRandomEntity()
{
    var isPlayer = new Random().Next(2) == 0;
    CombatEntity entity = isPlayer ? new Player() 
    { 
        Name = $"玩家{CombatEntities.Count + 1}", 
        INIT = new Random().Next(1,21),
        Skills = new[] { "剑术", "潜行" },
        PlayerAttributes = new List<NameValuePair> { new NameValuePair("HP", "100"), new NameValuePair("MP", "50") }
    } : new Monster()
    {
        Name = $"怪物{CombatEntities.Count + 1}",
        INIT = new Random().Next(1,21),
        Abilities = new[] { "咆哮", "爪击" },
        MonsterStats = new List<NameValuePair> { new NameValuePair("HP", "150"), new NameValuePair("防御", "20") }
    };
    CombatEntities.Add(entity);
}

二、按INIT自动排序

使用CollectionViewSource实现动态排序,绑定到DataGrid:

<Window.Resources>
    <CollectionViewSource x:Key="CombatEntitiesView" Source="{Binding CombatEntities}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="INIT" Direction="Descending"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</Window.Resources>

<!-- DataGrid绑定到视图 -->
<DataGrid ItemsSource="{Binding Source={StaticResource CombatEntitiesView}}" AutoGenerateColumns="False">

注:需要导入命名空间xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"

三、数组转文本显示

实现IValueConverter将数组转为逗号分隔的字符串:

public class ArrayToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string[] array)
        {
            return string.Join(", ", array);
        }
        return string.Empty;
    }

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

在XAML中引用并使用:

<Window.Resources>
    <local:ArrayToStringConverter x:Key="ArrayToStringConverter"/>
</Window.Resources>

<!-- DataGrid列示例 -->
<DataGridTextColumn Header="技能/能力" Binding="{Binding Skills, Converter={StaticResource ArrayToStringConverter}}"/>

四、NameValuePair悬停提示效果

自定义DataGridTemplateColumn,使用带下划线的TextBlock,并绑定ToolTip显示Value:

<DataGridTemplateColumn Header="属性/状态">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <WrapPanel>
                <!-- 针对Player的属性 -->
                <ItemsControl ItemsSource="{Binding PlayerAttributes}" Visibility="{Binding PlayerAttributes, Converter={StaticResource NullOrEmptyToVisibilityConverter}}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}" TextDecorations="Underline" Margin="0 0 5 0" Cursor="Help">
                                <TextBlock.ToolTip>
                                    <TextBlock Text="{Binding Value}"/>
                                </TextBlock.ToolTip>
                            </TextBlock>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
                <!-- 针对Monster的属性 -->
                <ItemsControl ItemsSource="{Binding MonsterStats}" Visibility="{Binding MonsterStats, Converter={StaticResource NullOrEmptyToVisibilityConverter}}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}" TextDecorations="Underline" Margin="0 0 5 0" Cursor="Help">
                                <TextBlock.ToolTip>
                                    <TextBlock Text="{Binding Value}"/>
                                </TextBlock.ToolTip>
                            </TextBlock>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </WrapPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

注:需要额外实现NullOrEmptyToVisibilityConverter来控制不同实体类型的属性面板显示/隐藏,或者使用DataTemplateSelector区分Player和Monster的单元格模板,实现更优雅的类型区分。

五、实时编辑支持

只要你的实体类实现了INotifyPropertyChanged(如上面的CombatEntity基类),且DataGrid的列绑定到实体的可写属性,就能支持实时编辑。如果需要自定义编辑模板,同样可以用DataGridTemplateColumn的CellEditingTemplate来实现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:45:28