扩展之前的C# WPF项目,明确界面设计(包含首页、数据库查询、增加、修改页面),并使用数据库(以SQLite为例)存储不同兵器的属性。每个兵器类型(枪支、大炮、飞机、坦克、卫星)将有独特的属性,存储在数据库中,并提供详细的兵器特性说明。我会使用DDD模式,提供完整的代码结构和实现细节。
项目结构
WeaponSystem
├── Domain
│ ├── Entities
│ │ ├── Weapon.cs (抽象类)
│ │ ├── Gun.cs
│ │ ├── Cannon.cs
│ │ ├── Aircraft.cs
│ │ ├── Tank.cs
│ │ ├── Satellite.cs
│ ├── Interfaces
│ │ ├── IWeapon.cs
│ │ ├── IWeaponRepository.cs
│ ├── ValueObjects
│ │ ├── WeaponCharacteristics.cs
├── Application
│ ├── Services
│ │ ├── WeaponService.cs
│ ├── DTOs
│ │ ├── WeaponDTO.cs
│ │ ├── GunDTO.cs, CannonDTO.cs, etc.
├── Infrastructure
│ ├── Repositories
│ │ ├── WeaponRepository.cs
│ ├── Data
│ │ ├── WeaponDbContext.cs
├── Presentation
│ ├── ViewModels
│ │ ├── MainViewModel.cs
│ │ ├── HomeViewModel.cs
│ │ ├── QueryViewModel.cs
│ │ ├── AddViewModel.cs
│ │ ├── UpdateViewModel.cs
│ ├── Views
│ │ ├── MainWindow.xaml
│ │ ├── HomeView.xaml
│ │ ├── QueryView.xaml
│ │ ├── AddView.xaml
│ │ ├── UpdateView.xaml
1. 兵器特性详解
每种兵器有通用属性(ID、名称、射程、威力、重量)和独特属性,存储在数据库中。以下是每种兵器的特性和使用场景:
-
枪支 (Gun):
- 特性: 轻便、射速快、适合近距离作战,维护成本低。
- 独特属性:
FireRate
(射速,单位:发/分钟)AmmoType
(弹药类型,如子弹、霰弹)
- 使用场景: 步兵作战、城市战、快速反应任务。
- 任务类型: CloseRange(近距离作战)。
-
大炮 (Cannon):
- 特性: 射程远、威力大、部署时间长,适合固定阵地。
- 独特属性:
BarrelLength
(炮管长度,单位:米)ShellType
(炮弹类型,如高爆、穿甲)
- 使用场景: 远程火力支援、防线压制。
- 任务类型: LongRange(远程轰炸)。
-
飞机 (Aircraft):
- 特性: 高速、机动性强、可执行多种任务(轰炸、侦察)。
- 独特属性:
MaxSpeed
(最大速度,单位:马赫)PayloadCapacity
(载弹量,单位:吨)
- 使用场景: 空中支援、战略轰炸、侦察。
- 任务类型: AirSupport(空中支援)。
-
坦克 (Tank):
- 特性: 重装甲、强火力、适合地面推进。
- 独特属性:
ArmorThickness
(装甲厚度,单位:毫米)EnginePower
(引擎功率,单位:马力)
- 使用场景: 地面突击、防守阵地。
- 任务类型: GroundAssault(地面突击)。
-
卫星 (Satellite):
- 特性: 太空部署、提供侦察或通信支持。
- 独特属性:
OrbitAltitude
(轨道高度,单位:公里)SensorType
(传感器类型,如光学、雷达)
- 使用场景: 情报收集、通信支持。
- 任务类型: Reconnaissance(侦察)。
2. 领域层 (Domain)
2.1 接口 (IWeapon.cs)
namespace WeaponSystem.Domain.Interfaces
{
public interface IWeapon
{
string Id { get; }
string Name { get; }
WeaponCharacteristics Characteristics { get; }
void UseWeapon(string missionType);
string GetFeatures();
}
}
2.2 抽象类 (Weapon.cs)
namespace WeaponSystem.Domain.Entities
{
public abstract class Weapon : IWeapon
{
public string Id { get; protected set; }
public string Name { get; protected set; }
public WeaponCharacteristics Characteristics { get; protected set; }
protected Weapon(string id, string name, WeaponCharacteristics characteristics)
{
Id = id;
Name = name;
Characteristics = characteristics;
}
public abstract void UseWeapon(string missionType);
public abstract string GetFeatures();
}
}
2.3 值对象 (WeaponCharacteristics.cs)
namespace WeaponSystem.Domain.ValueObjects
{
public class WeaponCharacteristics
{
public double Range { get; set; }
public double Power { get; set; }
public double Weight { get; set; }
public Dictionary<string, string> SpecificAttributes { get; set; } // 存储独特属性
public WeaponCharacteristics(double range, double power, double weight, Dictionary<string, string> specificAttributes)
{
Range = range;
Power = power;
Weight = weight;
SpecificAttributes = specificAttributes;
}
}
}
2.4 具体实体类
以Gun.cs
为例,其余类类似,仅独特属性不同。
namespace WeaponSystem.Domain.Entities
{
public class Gun : Weapon
{
public Gun(string id, string name, WeaponCharacteristics characteristics)
: base(id, name, characteristics)
{
}
public override void UseWeapon(string missionType)
{
Console.WriteLine($"Gun {Name} used for {missionType}. Effective for close-range infantry support.");
}
public override string GetFeatures()
{
var fireRate = Characteristics.SpecificAttributes.GetValueOrDefault("FireRate");
var ammoType = Characteristics.SpecificAttributes.GetValueOrDefault("AmmoType");
return $"Gun: {Name}, Range: {Characteristics.Range}km, Power: {Characteristics.Power}, Weight: {Characteristics.Weight}t, FireRate: {fireRate}, AmmoType: {ammoType}";
}
}
// Cannon.cs
public class Cannon : Weapon
{
public Cannon(string id, string name, WeaponCharacteristics characteristics)
: base(id, name, characteristics) { }
public override void UseWeapon(string missionType)
{
Console.WriteLine($"Cannon {Name} used for {missionType}. Ideal for long-range bombardment.");
}
public override string GetFeatures()
{
var barrelLength = Characteristics.SpecificAttributes.GetValueOrDefault("BarrelLength");
var shellType = Characteristics.SpecificAttributes.GetValueOrDefault("ShellType");
return $"Cannon: {Name}, Range: {Characteristics.Range}km, Power: {Characteristics.Power}, Weight: {Characteristics.Weight}t, BarrelLength: {barrelLength}, ShellType: {shellType}";
}
}
// Aircraft.cs, Tank.cs, Satellite.cs 类似实现,略
}
2.5 仓储接口 (IWeaponRepository.cs)
namespace WeaponSystem.Domain.Interfaces
{
public interface IWeaponRepository
{
void Add(Weapon weapon);
void Update(Weapon weapon);
void Delete(string id);
Weapon GetById(string id);
IEnumerable<Weapon> GetAll();
IEnumerable<Weapon> QueryByType(string weaponType);
}
}
3. 应用层 (Application)
3.1 DTOs
为每种兵器定义特定的DTO,包含独特属性。
namespace WeaponSystem.Application.DTOs
{
public abstract class WeaponDTO
{
public string Id { get; set; }
public string Name { get; set; }
public double Range { get; set; }
public double Power { get; set; }
public double Weight { get; set; }
public string Type { get; set; }
}
public class GunDTO : WeaponDTO
{
public string FireRate { get; set; }
public string AmmoType { get; set; }
}
public class CannonDTO : WeaponDTO
{
public string BarrelLength { get; set; }
public string ShellType { get; set; }
}
// AircraftDTO, TankDTO, SatelliteDTO 类似,略
}
3.2 服务 (WeaponService.cs)
using WeaponSystem.Domain.Entities;
using WeaponSystem.Domain.Interfaces;
namespace WeaponSystem.Application.Services
{
public class WeaponService
{
private readonly IWeaponRepository _repository;
public WeaponService(IWeaponRepository repository)
{
_repository = repository;
}
public void AddWeapon(WeaponDTO dto)
{
var characteristics = new WeaponCharacteristics(
dto.Range, dto.Power, dto.Weight,
dto switch
{
GunDTO gun => new Dictionary<string, string> { { "FireRate", gun.FireRate }, { "AmmoType", gun.AmmoType } },
CannonDTO cannon => new Dictionary<string, string> { { "BarrelLength", cannon.BarrelLength }, { "ShellType", cannon.ShellType } },
// 其他类型类似
_ => throw new ArgumentException("Invalid weapon type")
});
Weapon weapon = dto.Type switch
{
"Gun" => new Gun(dto.Id, dto.Name, characteristics),
"Cannon" => new Cannon(dto.Id, dto.Name, characteristics),
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
_repository.Add(weapon);
}
public void UpdateWeapon(WeaponDTO dto)
{
var characteristics = new WeaponCharacteristics(
dto.Range, dto.Power, dto.Weight,
dto switch
{
GunDTO gun => new Dictionary<string, string> { { "FireRate", gun.FireRate }, { "AmmoType", gun.AmmoType } },
CannonDTO cannon => new Dictionary<string, string> { { "BarrelLength", cannon.BarrelLength }, { "ShellType", cannon.ShellType } },
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
});
Weapon weapon = dto.Type switch
{
"Gun" => new Gun(dto.Id, dto.Name, characteristics),
"Cannon" => new Cannon(dto.Id, dto.Name, characteristics),
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
_repository.Update(weapon);
}
public void DeleteWeapon(string id) => _repository.Delete(id);
public WeaponDTO GetWeaponById(string id)
{
var weapon = _repository.GetById(id);
if (weapon == null) return null;
return weapon switch
{
Gun gun => new GunDTO
{
Id = gun.Id,
Name = gun.Name,
Range = gun.Characteristics.Range,
Power = gun.Characteristics.Power,
Weight = gun.Characteristics.Weight,
Type = "Gun",
FireRate = gun.Characteristics.SpecificAttributes.GetValueOrDefault("FireRate"),
AmmoType = gun.Characteristics.SpecificAttributes.GetValueOrDefault("AmmoType")
},
Cannon cannon => new CannonDTO
{
Id = cannon.Id,
Name = cannon.Name,
Range = cannon.Characteristics.Range,
Power = cannon.Characteristics.Power,
Weight = cannon.Characteristics.Weight,
Type = "Cannon",
BarrelLength = cannon.Characteristics.SpecificAttributes.GetValueOrDefault("BarrelLength"),
ShellType = cannon.Characteristics.SpecificAttributes.GetValueOrDefault("ShellType")
},
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
}
public IEnumerable<WeaponDTO> GetAllWeapons() => _repository.GetAll().Select(MapToDTO);
public IEnumerable<WeaponDTO> QueryWeaponsByType(string weaponType) => _repository.QueryByType(weaponType).Select(MapToDTO);
private WeaponDTO MapToDTO(Weapon weapon) => weapon switch
{
Gun gun => new GunDTO
{
Id = gun.Id,
Name = gun.Name,
Range = gun.Characteristics.Range,
Power = gun.Characteristics.Power,
Weight = gun.Characteristics.Weight,
Type = "Gun",
FireRate = gun.Characteristics.SpecificAttributes.GetValueOrDefault("FireRate"),
AmmoType = gun.Characteristics.SpecificAttributes.GetValueOrDefault("AmmoType")
},
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
public string RecommendWeapon(string missionType)
{
return missionType switch
{
"CloseRange" => "Gun",
"LongRange" => "Cannon",
"AirSupport" => "Aircraft",
"GroundAssault" => "Tank",
"Reconnaissance" => "Satellite",
_ => "Unknown mission type"
};
}
}
}
4. 基础设施层 (Infrastructure)
4.1 数据库上下文 (WeaponDbContext.cs)
使用Entity Framework Core和SQLite存储兵器数据。
using Microsoft.EntityFrameworkCore;
using WeaponSystem.Domain.Entities;
using WeaponSystem.Domain.ValueObjects;
namespace WeaponSystem.Infrastructure.Data
{
public class WeaponDbContext : DbContext
{
public DbSet<WeaponEntity> Weapons { get; set; }
public WeaponDbContext(DbContextOptions<WeaponDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<WeaponEntity>()
.OwnsOne(w => w.Characteristics, c =>
{
c.Property(x => x.Range).HasColumnName("Range");
c.Property(x => x.Power).HasColumnName("Power");
c.Property(x => x.Weight).HasColumnName("Weight");
c.Property(x => x.SpecificAttributes).HasConversion(
v => System.Text.Json.JsonSerializer.Serialize(v, null),
v => System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, string>>(v, null));
});
}
}
public class WeaponEntity
{
public string Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public WeaponCharacteristics Characteristics { get; set; }
}
}
4.2 仓储实现 (WeaponRepository.cs)
using Microsoft.EntityFrameworkCore;
using WeaponSystem.Domain.Entities;
using WeaponSystem.Domain.Interfaces;
namespace WeaponSystem.Infrastructure.Repositories
{
public class WeaponRepository : IWeaponRepository
{
private readonly WeaponDbContext _context;
public WeaponRepository(WeaponDbContext context)
{
_context = context;
}
public void Add(Weapon weapon)
{
var entity = new WeaponEntity
{
Id = weapon.Id,
Name = weapon.Name,
Type = weapon.GetType().Name,
Characteristics = weapon.Characteristics
};
_context.Weapons.Add(entity);
_context.SaveChanges();
}
public void Update(Weapon weapon)
{
var entity = _context.Weapons.Find(weapon.Id);
if (entity != null)
{
entity.Name = weapon.Name;
entity.Type = weapon.GetType().Name;
entity.Characteristics = weapon.Characteristics;
_context.SaveChanges();
}
}
public void Delete(string id)
{
var entity = _context.Weapons.Find(id);
if (entity != null)
{
_context.Weapons.Remove(entity);
_context.SaveChanges();
}
}
public Weapon GetById(string id)
{
var entity = _context.Weapons.Find(id);
if (entity == null) return null;
return entity.Type switch
{
"Gun" => new Gun(entity.Id, entity.Name, entity.Characteristics),
"Cannon" => new Cannon(entity.Id, entity.Name, entity.Characteristics),
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
}
public IEnumerable<Weapon> GetAll() => _context.Weapons.ToList().Select(MapToWeapon);
public IEnumerable<Weapon> QueryByType(string weaponType) => _context.Weapons
.Where(w => w.Type == weaponType)
.ToList()
.Select(MapToWeapon);
private Weapon MapToWeapon(WeaponEntity entity) => entity.Type switch
{
"Gun" => new Gun(entity.Id, entity.Name, entity.Characteristics),
"Cannon" => new Cannon(entity.Id, entity.Name, entity.Characteristics),
// 其他类型
_ => throw new ArgumentException("Invalid weapon type")
};
}
}
5. 表现层 (Presentation)
5.1 界面设计
- 首页 (HomeView.xaml): 显示欢迎信息和推荐兵器功能。
- 数据库查询 (QueryView.xaml): 显示所有兵器,允许按类型筛选。
- 增加 (AddView.xaml): 提供表单输入兵器属性,动态调整字段。
- 修改 (UpdateView.xaml): 编辑已有兵器,动态加载属性。
5.1.1 首页 (HomeView.xaml)
<UserControl x:Class="WeaponSystem.Presentation.Views.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="10">
<TextBlock Text="Welcome to Weapon System" FontSize="20" Margin="5"/>
<TextBox Text="{Binding MissionType}" Width="200" Margin="5"/>
<TextBlock Text="{Binding RecommendedWeapon}" Margin="5"/>
</StackPanel>
</UserControl>
5.1.2 查询页面 (QueryView.xaml)
<UserControl x:Class="WeaponSystem.Presentation.Views.QueryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<ComboBox SelectedItem="{Binding SelectedType}" Width="100" Margin="5">
<ComboBoxItem>All</ComboBoxItem>
<ComboBoxItem>Gun</ComboBoxItem>
<ComboBoxItem>Cannon</ComboBoxItem>
<ComboBoxItem>Aircraft</ComboBoxItem>
<ComboBoxItem>Tank</ComboBoxItem>
<ComboBoxItem>Satellite</ComboBoxItem>
</ComboBox>
<Button Content="Query" Command="{Binding QueryCommand}" Margin="5"/>
</StackPanel>
<DataGrid Grid.Row="1" ItemsSource="{Binding Weapons}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Type" Binding="{Binding Type}"/>
<DataGridTextColumn Header="Range" Binding="{Binding Range}"/>
<DataGridTextColumn Header="Power" Binding="{Binding Power}"/>
<DataGridTextColumn Header="Weight" Binding="{Binding Weight}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
5.1.3 增加页面 (AddView.xaml)
<UserControl x:Class="WeaponSystem.Presentation.Views.AddView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="10">
<ComboBox SelectedItem="{Binding SelectedWeapon.Type}" Width="100" Margin="5">
<ComboBoxItem>Gun</ComboBoxItem>
<ComboBoxItem>Cannon</ComboBoxItem>
<ComboBoxItem>Aircraft</ComboBoxItem>
<ComboBoxItem>Tank</ComboBoxItem>
<ComboBoxItem>Satellite</ComboBoxItem>
</ComboBox>
<TextBox Text="{Binding SelectedWeapon.Name}" Width="200" Margin="5" Prompt="Name"/>
<TextBox Text="{Binding SelectedWeapon.Range}" Width="200" Margin="5" Prompt="Range (km)"/>
<TextBox Text="{Binding SelectedWeapon.Power}" Width="200" Margin="5" Prompt="Power"/>
<TextBox Text="{Binding SelectedWeapon.Weight}" Width="200" Margin="5" Prompt="Weight (t)"/>
<!-- 动态字段,基于兵器类型 -->
<ContentControl Content="{Binding DynamicFields}"/>
<Button Content="Add" Command="{Binding AddCommand}" Margin="5"/>
</StackPanel>
</UserControl>
5.1.4 修改页面 (UpdateView.xaml)
与AddView.xaml
类似,但预加载选中兵器的属性。
5.2 ViewModel
5.2.1 主ViewModel (MainViewModel.cs)
using WeaponSystem.Application.Services;
using System.Windows.Controls;
using System.Windows.Input;
namespace WeaponSystem.Presentation.ViewModels
{
public class MainViewModel : INotifyPropertyChanged
{
private UserControl _currentView;
public UserControl CurrentView
{
get => _currentView;
set { _currentView = value; OnPropertyChanged(nameof(CurrentView)); }
}
public ICommand HomeCommand { get; }
public ICommand QueryCommand { get; }
public ICommand AddCommand { get; }
public ICommand UpdateCommand { get; }
public MainViewModel(WeaponService weaponService)
{
HomeCommand = new RelayCommand(() => CurrentView = new HomeView { DataContext = new HomeViewModel(weaponService) });
QueryCommand = new RelayCommand(() => CurrentView = new QueryView { DataContext = new QueryViewModel(weaponService) });
AddCommand = new RelayCommand(() => CurrentView = new AddView { DataContext = new AddViewModel(weaponService) });
UpdateCommand = new RelayCommand(() => CurrentView = new UpdateView { DataContext = new UpdateViewModel(weaponService) });
CurrentView = new HomeView { DataContext = new HomeViewModel(weaponService) };
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class RelayCommand : ICommand
{
private readonly Action _execute;
public RelayCommand(Action execute) => _execute = execute;
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _execute();
}
}
5.2.2 首页ViewModel (HomeViewModel.cs)
using WeaponSystem.Application.Services;
namespace WeaponSystem.Presentation.ViewModels
{
public class HomeViewModel : INotifyPropertyChanged
{
private readonly WeaponService _weaponService;
private string _missionType;
public string MissionType
{
get => _missionType;
set { _missionType = value; OnPropertyChanged(nameof(MissionType)); OnPropertyChanged(nameof(RecommendedWeapon)); }
}
public string RecommendedWeapon => _weaponService.RecommendWeapon(MissionType);
public HomeViewModel(WeaponService weaponService)
{
_weaponService = weaponService;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
5.2.3 查询ViewModel (QueryViewModel.cs)
using WeaponSystem.Application.DTOs;
using WeaponSystem.Application.Services;
using System.Collections.ObjectModel;
namespace WeaponSystem.Presentation.ViewModels
{
public class QueryViewModel : INotifyPropertyChanged
{
private readonly WeaponService _weaponService;
private string _selectedType;
public ObservableCollection<WeaponDTO> Weapons { get; set; }
public string SelectedType
{
get => _selectedType;
set { _selectedType = value; OnPropertyChanged(nameof(SelectedType)); QueryWeapons(); }
}
public ICommand QueryCommand { get; }
public QueryViewModel(WeaponService weaponService)
{
_weaponService = weaponService;
Weapons = new ObservableCollection<WeaponDTO>();
QueryCommand = new RelayCommand(QueryWeapons);
SelectedType = "All";
}
private void QueryWeapons()
{
Weapons.Clear();
var weapons = SelectedType == "All" ? _weaponService.GetAllWeapons() : _weaponService.QueryWeaponsByType(SelectedType);
foreach (var weapon in weapons)
Weapons.Add(weapon);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
5.2.4 增加ViewModel (AddViewModel.cs)
using WeaponSystem.Application.DTOs;
using WeaponSystem.Application.Services;
using System.Windows.Controls;
namespace WeaponSystem.Presentation.ViewModels
{
public class AddViewModel : INotifyPropertyChanged
{
private readonly WeaponService _weaponService;
private WeaponDTO _selectedWeapon;
private UserControl _dynamicFields;
public WeaponDTO SelectedWeapon
{
get => _selectedWeapon;
set
{
_selectedWeapon = value;
UpdateDynamicFields();
OnPropertyChanged(nameof(SelectedWeapon));
}
}
public UserControl DynamicFields
{
get => _dynamicFields;
set { _dynamicFields = value; OnPropertyChanged(nameof(DynamicFields)); }
}
public ICommand AddCommand { get; }
public AddViewModel(WeaponService weaponService)
{
_weaponService = weaponService;
SelectedWeapon = new GunDTO { Id = Guid.NewGuid().ToString(), Type = "Gun" };
AddCommand = new RelayCommand(AddWeapon);
UpdateDynamicFields();
}
private void AddWeapon()
{
_weaponService.AddWeapon(SelectedWeapon);
}
private void UpdateDynamicFields()
{
DynamicFields = SelectedWeapon.Type switch
{
"Gun" => new UserControl
{
Content = new StackPanel
{
Children =
{
new TextBox { Text = ((GunDTO)SelectedWeapon).FireRate, Width = 200, Margin = new Thickness(5) },
new TextBox { Text = ((GunDTO)SelectedWeapon).AmmoType, Width = 200, Margin = new Thickness(5) }
}
}
},
"Cannon" => new UserControl
{
Content = new StackPanel
{
Children =
{
new TextBox { Text = ((CannonDTO)SelectedWeapon).BarrelLength, Width = 200, Margin = new Thickness(5) },
new TextBox { Text = ((CannonDTO)SelectedWeapon).ShellType, Width = 200, Margin = new Thickness(5) }
}
}
},
// 其他类型
_ => new UserControl()
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
5.2.5 修改ViewModel (UpdateViewModel.cs)
与AddViewModel.cs
类似,但包含从数据库加载已有兵器的逻辑。
5.3 主窗口 (MainWindow.xaml)
<Window x:Class="WeaponSystem.Presentation.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Weapon System" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content="Home" Command="{Binding HomeCommand}" Margin="5"/>
<Button Content="Query" Command="{Binding QueryCommand}" Margin="5"/>
<Button Content="Add" Command="{Binding AddCommand}" Margin="5"/>
<Button Content="Update" Command="{Binding UpdateCommand}" Margin="5"/>
</StackPanel>
<ContentControl Grid.Row="1" Content="{Binding CurrentView}"/>
</Grid>
</Window>
5.4 代码-behind (MainWindow.xaml.cs)
using Microsoft.EntityFrameworkCore;
using WeaponSystem.Application.Services;
using WeaponSystem.Infrastructure.Data;
using WeaponSystem.Infrastructure.Repositories;
using WeaponSystem.Presentation.ViewModels;
using System.Windows;
namespace WeaponSystem.Presentation.Views
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var options = new DbContextOptionsBuilder<WeaponDbContext>()
.UseSqlite("Data Source=weapons.db")
.Options;
var context = new WeaponDbContext(options);
context.Database.EnsureCreated();
var weaponService = new WeaponService(new WeaponRepository(context));
DataContext = new MainViewModel(weaponService);
}
}
}
6. 如何运行
- 创建WPF项目,添加上述文件。
- 安装NuGet包:
Microsoft.EntityFrameworkCore.Sqlite
System.Text.Json
- 确保项目引用正确,运行
MainWindow.xaml
。 - 数据库文件
weapons.db
会在运行时自动创建。 - 通过界面切换首页、查询、增加、修改页面,输入或查询兵器数据。
7. 扩展建议
- 动态表单优化:使用数据模板(DataTemplate)动态生成兵器特定属性的输入字段。
- 验证逻辑:在
WeaponService
中添加输入验证(如射程不能为负)。 - 日志记录:集成Serilog记录操作日志。
- 单元测试:为
WeaponService
和WeaponRepository
编写单元测试。 - UI美化:添加兵器图标、3D模型预览或动画效果。
如果需要更详细的某部分代码或进一步优化,请告诉我!