I'm writing my first app for Windows Phone and I encountered a problem. I've created a button that is supposed to generate a random entry from my XML on the textblock. The XML itself looks like this:
<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>
However there is a problem. When I press a button it sometimes generates random entry, but sometimes it just prints a "Type" of an entry, and sometimes both entry and the type. How can I prevent this from happening? I still want to load a Type of an entry for future functionality, but I don't want it to be displayed in a textblock. Here is my code:
Class loading an XML file:
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");
}
}
}
}
}
And here is my MainPage class:
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);
}
}
}
Thank you in advance.
I would structure the code very differently:
if
statements - you're doing basically the same thing in every situation. You can always use a HashSet<string>
for known types, if you want to skip other onesusing
statement for IsolatedStorageFile
So something like:
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;
}
}
}
See more on this question at Stackoverflow