如何在WPF中实现自定义DataGrid以展示玩家与怪物信息?
WPF实现动态玩家/怪物信息表格方案
WPF完全可以实现你要求的所有功能,无需更换前端框架。以下是针对你的需求的具体实现方案:
一、数据结构与实时更新基础
- 定义统一的实体基类(或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; } // 怪物专属属性... }
- 使用
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
相关产品推荐
相关产品推荐

