简体   繁体   English

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

[英]How to add variables and link them to a combobox from an external file?

I have a program where the user can choose a "class" of ships based off a combobox. 我有一个程序,用户可以根据组合框选择“类别”的飞船。 Currently all the stats and classes are hard coded into the program. 当前,所有统计信息和类均已硬编码到程序中。 The problem is I want to be able to add extra ship types as needed. 问题是我希望能够根据需要添加其他船型。 Preferably in a simple way that my friend (who knows almost nothing about code) and also add ships (the plan is once I finish, I'll give a copy to him to use). 最好以一种简单的方式,让我的朋友(几乎对代码一无所知)并添加船(计划是我完成后,我会给他一个副本供使用)。 Each ship uses a name and 3 stats. 每艘船使用一个名称和3个统计数据。 The current hardcoded codes I have is - 我目前使用的硬编码为-

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;
    }

The items in the combobox cmb_Class is all hardcoded into the WPF forms xml and the labels are just how I'm showing the stats. 组合框cmb_Class中的项目都被硬编码到WPF表单xml中,标签正是我显示统计信息的方式。

Bonus issue: I can just make a secondary file for a similar group of "species" and their stats (yes, it's a sci-fi RPG type thing), but if there's a simple way to make them all in the same file, that'd be great. 额外的问题:我可以为一组类似的“物种”及其统计信息创建一个辅助文件(是的,这是科幻RPG类型的东西),但是如果有一种简单的方法可以将它们全部放在同一个文件中,会很棒。

here is what you might like to use. 这是您可能想要使用的。 it's not using XML, it's using CSV but you can easily extend it. 它没有使用XML,而是使用CSV,但是您可以轻松扩展它。

first you'll need a class to represent your ships, like below. 首先,您需要一个类来代表您的飞船,如下所示。

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

After this you'll need a way to read your ships from some sort of data source: file, DB, etc. this source can change ofter so you'll be better of abstracting this behind an interface like below. 之后,您将需要一种从某种数据源(文件,数据库等)中读取船的方法。此源可能会发生变化,因此最好将其抽象为如下所示的接口。

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

After you decide where you'll get the ships from you can write that in an implementation of the IShipRepository interface. 决定从何处获得发货后,可以在IShipRepository接口的实现中编写该代码。 The code below shows how to read it from a CSV file. 下面的代码显示了如何从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;
    }
}

all you have to do now is to use this CSVShipRepository in your code behind. 您现在要做的就是在后面的代码中使用此CSVShipRepository。 we'll use a little data binding for this like below. 我们将为此使用一些数据绑定,如下所示。

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));
    }
}

the corresponding XAML is below. 相应的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" />

hope this is what you need. 希望这是您所需要的。 it's simpler than XML since your friend doesn't know code. 它比XML简单,因为您的朋友不知道代码。 and here is some sample data 这是一些样本数据

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM