如何从外部文件添加变量并将其链接到组合框

本文关键字:链接 组合 从外部 文件 添加 变量 | 更新日期: 2023-09-27 18:11:59

我有一个程序,用户可以根据组合框选择船舶的"类别"。目前,所有的统计和类都硬编码到程序中。问题是我希望能够根据需要添加额外的船舶类型。最好以一种简单的方式让我的朋友(他对代码几乎一无所知)也添加舰船(计划是一旦我完成,我会给他一份副本使用)。每艘船都有一个名字和3个属性。我现有的硬编码代码是-

private void cmb_Class_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        shipClass = (cmb_Class.SelectedItem as ComboBoxItem).Content.ToString();
        if (shipClass == "Scout")
        {
            attack = 6;
            engine = 10;
            shield = 8;
        }
        if (shipClass == "Warship")
        {
            attack = 10;
            engine = 6;
            shield = 8;
        }
        if (shipClass == "Cargo")
        {
            attack = 8;
            engine = 6;
            shield = 10;
        }
        if (shipClass == "Starliner")
        {
            attack = 6;
            engine = 8;
            shield = 10;
        }
        if (shipClass == "Transport")
        {
            attack = 8;
            engine = 10;
            shield = 6;
        }
        if (shipClass == "Luxury")
        {
            attack = 8;
            engine = 8;
            shield = 8;
        }
        lbl_Attack.Content = attack;
        lbl_Engine.Content = engine;
        lbl_Shield.Content = shield;
    }

组合框cmb_Class中的项目都硬编码到WPF表单xml中,标签只是我显示统计数据的方式。

附加问题:我可以为类似的一组"物种"及其属性制作一个次要文件(是的,这是科幻RPG类型的东西),但如果有一种简单的方法将它们全部放在同一个文件中,那就太棒了。

如何从外部文件添加变量并将其链接到组合框

这是您可能喜欢使用的。它不是使用XML,而是使用CSV,但是你可以很容易地扩展它。

首先你需要一个类来代表你的船,如下所示。

public class Ship
{
    public string Class { get; set; }
    public int Attack { get; set; }
    public int Engine { get; set; }
    public int Shield { get; set; }
}

在此之后,你需要一种方法来读取你的船从某种数据源:文件,数据库等,这个源可以改变,所以你会更好地抽象它后面的接口,像下面。

interface IShipRepository
{
    List<Ship> GetShips();
}

决定了从哪里获得船只之后,可以在IShipRepository接口的实现中编写它。下面的代码显示了如何从CSV文件中读取它。

public class CSVShipRepository : IShipRepository
{
    private readonly string filePath;
    public CSVShipRepository(string filePath)
    {
        if (string.IsNullOrEmpty(filePath))
            throw new ArgumentNullException("filePath");
        this.filePath = filePath;
    }
    public List<Ship> GetShips()
    {
        var res = new List<Ship>();
        try
        {
            string fileData;
            using (var sr = new StreamReader(filePath))
            {
                fileData = sr.ReadToEnd();
            }
            //class, attack, engine, shield
            string[] lines = fileData.Split(new string[] { "'n" }, StringSplitOptions.RemoveEmptyEntries);
            bool first = true;
            foreach (var line in lines)
            {
                if (first)
                {//jump over the first line (the CSV header line)
                    first = false; continue;
                }
                string[] values = line.Split(new string[] { "," }, StringSplitOptions.None)
                    .Select(p=>p.Trim()).ToArray();
                if (values.Length != 4) continue;
                var ship = new Ship() { 
                    Class=values[0],
                    Attack=int.Parse(values[1]),
                    Engine = int.Parse(values[2]),
                    Shield = int.Parse(values[3]),
                };
                res.Add(ship);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine("error reading file: " + ex.Message);
        }
        return res;
    }
}

您现在所要做的就是在代码中使用这个CSVShipRepository。我们将使用一些数据绑定,如下所示。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private IShipRepository repository = new CSVShipRepository("d:''test_data.csv");
    private List<Ship> ships;
    private Ship selectedShip;
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
    public List<Ship> Ships
    {
        get
        {
            if (ships == null)
                ships = repository.GetShips();
            return ships;
        }
    }
    public Ship SelectedShip
    {
        get { return selectedShip; }
        set
        {
            if (selectedShip == value) return;
            selectedShip = value;
            NotifyChanged("SelectedShip");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

对应的XAML在下面。

<ComboBox ItemsSource="{Binding Ships}" 
              SelectedItem="{Binding SelectedShip, Mode=TwoWay}" Margin="2">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Class}"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Row="1" Text="{Binding SelectedShip.Attack}" Margin="3" />
<TextBlock Grid.Row="2" Text="{Binding SelectedShip.Engine}" Margin="3" />
<TextBlock Grid.Row="3" Text="{Binding SelectedShip.Shield}" Margin="3" />

希望这是你需要的。它比XML简单,因为您的朋友不懂代码。这里是一些样本数据

class, attack, engine, shield
demo, 1, 2, 3
demo2, 4, 5, 6