【问题标题】:Reading a random entry from XML in Windows Phone在 Windows Phone 中从 XML 读取随机条目
【发布时间】:2014-03-30 11:49:28
【问题描述】:

我正在为 Windows Phone 编写我的第一个应用程序,但遇到了问题。我创建了一个按钮,该按钮应该从文本块上的 XML 生成随机条目。 XML 本身如下所示:

  <Activities>

    <Activity Type="Cooking">
      Cook some Mexican food
    </Activity>

    <Activity Type="Art">
      Draw a picture
    </Activity>

    <Activity Type="Language">
      Learn 5 words in Polish you didn't know yet
    </Activity>

    <Activity Type="Science">
      Write a simple program in C
    </Activity>

    <Activity Type="Sport">
      Go to the swimming pool
    </Activity>

  </Activities>

但是有一个问题。当我按下按钮时,它有时会生成随机条目,但有时它只打印条目的“类型”,有时会同时打印条目和类型。我怎样才能防止这种情况发生?我仍然想为将来的功能加载条目的类型,但我不希望它显示在文本块中。这是我的代码:

类加载一个 XML 文件:

namespace ReadXMLfromFile
{
    public class Activities
    {
        private List<String> activities;

        public String getActivities(int i)
        {
            return activities.ElementAt(i);

        }

        public List<String> getActivities()
        {
            return activities;
        }

        public Activities()
        {

            IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication();

            activities = new List<String>();

            if (ISF.FileExists("Activities.xml"))
            {
                IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream("Activities.xml", FileMode.Open, FileAccess.Read, FileShare.Read, ISF);

                var aclist = from c in XElement.Load(isoStream).Element("Activities").Elements()
                             select c;
                ISF.Dispose();
                isoStream.Dispose();

                foreach (var el in aclist)
                {
                    this.activities.Add(el.Value);

                    if ((string)el.Attribute("Type") == "Cooking")
                        this.activities.Add("Cooking");
                    else

                    if ((string)el.Attribute("Type") == "Art")
                         this.activities.Add("Art");
                    else

                    if ((string)el.Attribute("Type") == "Language")
                        this.activities.Add("Language");
                    else

                    if ((string)el.Attribute("Type") == "Science")
                        this.activities.Add("Science");
                    else

                    if ((string)el.Attribute("Type") == "Sport")
                        this.activities.Add("Sport");
                } 
             }
            else
            {
                ISF.Dispose();
                var aclist = from c in XElement.Load("Assets/Activities.xml").Element("Activities").Elements()
                             select c;

                foreach (var el in aclist)
                {
                    this.activities.Add(el.Value);

                    if ((string)el.Attribute("Type") == "Cooking")
                        this.activities.Add("Cooking");
                    else

                        if ((string)el.Attribute("Type") == "Art")
                            this.activities.Add("Art");
                        else

                            if ((string)el.Attribute("Type") == "Language")
                                this.activities.Add("Language");
                            else

                                if ((string)el.Attribute("Type") == "Science")
                                    this.activities.Add("Science");
                                else

                                    if ((string)el.Attribute("Type") == "Sport")
                                        this.activities.Add("Sport");
                } 
            }

        }
    }
}

这是我的 MainPage 类:

namespace ActivityManager
{
    public partial class MainPage : PhoneApplicationPage
    {

        private Activities ac;
        private Random activityNumber;
        private int actualActivityNumber;


        // Constructor
        public MainPage()
        {
            InitializeComponent();
            ac = new Activities();

        }


        private void RandomButton_Click(object sender, RoutedEventArgs e)
        {
            RandomTextBox.Text="0";
           activityNumber = new Random();
            actualActivityNumber = activityNumber.Next(0, ac.getActivities().Count);
            RandomTextBox.Text = ac.getActivities(actualActivityNumber);

        }
    }
}

提前谢谢你。

【问题讨论】:

  • 您将元素 的值都添加到列表中 - 为什么?我建议您使用TypeDescription 属性创建自己的类...
  • 我这样做是因为我需要它来实现我的应用程序的不同功能。但是,如果我试图只加载没有类型的值,我会在 public String getActivities(int i) 中得到“ArgumentOutOfRangeException 未处理”
  • 好吧,在不知道“不同功能”的情况下,很难理解为什么要这样构建代码 - 只要您选择适当的索引,您就不应该得到 ArgumentOutOfRangeException .
  • 哦,我现在修复了异常。原来我对代码的注释太多了。如果不添加Type,它实际上可以按预期工作。但是,我想使用ListBoxCheckBoxes 为我的XML 中的活动创建一个浏览器。我希望能够根据类型显示它们(CheckBox 仅显示具有选中类型的活动)。我想我需要他们 ActivityType 一起这样做。
  • 这很好 - 但您应该将其表示为一种数据类型,而不是仅仅将类型和描述都添加到一个字符串列表中。看我回答中的代码。

标签: c# xml windows-phone-7


【解决方案1】:

我会以不同的方式构建代码非常

  • 为类型和描述创建一个类
  • 不要使用所有这些if 语句 - 在任何情况下您都在做基本相同的事情。如果您想跳过其他类型,您始终可以使用 HashSet&lt;string&gt; 来表示已知类型
  • 不要有两个不同位的代码都读取相同的 XML 结构
  • IsolatedStorageFile 使用using 语句

比如:

public class Activity
{
    public string Type { get; private set; }
    public string Description { get; private set; }

    public Activity(string type, string description)
    {
         Type = type;
         Description = description;
    }

    public static List<Activity> LoadActivities(XDocument doc)
    {
        return doc.Root
                  .Elements("Activity")
                  .Select(el => new Activity((string) el.Attribute("Type"),
                                             el.Value));
                  .ToList();
    }

    public static List<Activity> LoadActivities()
    {
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (store.FileExists("Activities.xml"))
            {
                 using (var stream = store.OpenFile("Activities.xml",
                                                    FileMode.Open))
                 {
                     return LoadActivities(XDocument.Load(stream));
                 }
            }
        }
        // No user file... load the default activities
        return LoadActivities(XDocument.Load("Assets/Activities.xml"));
    }
}

...

namespace ActivityManager
{
    public partial class MainPage : PhoneApplicationPage
    {
        private List<Activity> activities;
        private Random random;
        private int actualActivityNumber;


        // Constructor
        public MainPage()
        {
            InitializeComponent();
            activities = Activity.LoadActivities();
            // Initialize this *once* - not once per click
            random = new Random();
        }


        private void RandomButton_Click(object sender, RoutedEventArgs e)
        {
            int index = random.Next(activities.Count);
            RandomTextBox.Text = activities[index].Description;
        }
    }
}

【讨论】:

  • 哇,谢谢。这样看起来方便了很多。但是我尝试了你的代码,现在我在RandomTextBox.Text = activities[index].Description; 再次收到 ArgumentOutOfRangeException 知道为什么会这样吗?
  • @Tajgun92:如果你完全使用了我的代码,你真的不应该这样做。您可以为activities.Countindex 添加日志记录吗?
  • 我不知道你指的是什么。按下按钮后出现异常,我在 Locals 中看到 index 的值为 0,如果这就是你的意思
  • @Tajgun92:如果index 的值为0,但您仍然遇到异常,则表明activities 为空。在调试器中,你能看到任何活动吗?如果 activities.Count 为 0,我希望上一行会引发异常……您可能应该有一个特殊情况来处理没有任何活动的情况。
  • 我终于找到了问题所在。这是一个 XML 文件。我无意中没有在此处粘贴完整的 XML 文件,其中&lt;Activities&gt; 周围有一个额外的&lt;wraper&gt; 标签。 LoadActivites 一定是使用了错误的 Root。一旦我删除它,一切正常。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多