Silverlight 4.0 reading complex xml with linq - c#

I'm stuck with following XML problem.
This is my XML file:
<POIs lastUsedId="9000010">
<POI id="9000010" name="München"><Latitude>48.139126</Latitude><Longitude>11.5801863</Longitude>
<Address>muenchen</Address><PhotoDescription>Hofbräuhaus</PhotoDescription>
<Photos directory="_x002F_pics"><PhotoFile>pic4poi_9000010-01.jpg</PhotoFile>
<PhotoFile>pic4poi_9000010-02.jpg</PhotoFile><PhotoFile>pic4poi_9000010-03.jpg</PhotoFile>
<PhotoFile>pic4poi_9000010-04.jpg</PhotoFile></Photos>
<InformationFile>infos\info4poi_9000010.txt</InformationFile></POI>
</POIs>
And here is my code to read the file:
XDocument doc = XDocument.Load(s);
lastID = Int32.Parse(doc.Root.Attribute("lastUsedId").Value.ToString());
CultureInfo cultureInfo = new CultureInfo("en-GB");
var pois = from res in doc.Descendants("POI")
select new
{
id = Int32.Parse(res.Attribute("id").Value.ToString()),
name = res.Attribute("name").Value.ToString(),
latitude = Double.Parse(res.Element("Latitude").Value, cultureInfo),
longitude = Double.Parse(res.Element("Longitude").Value, cultureInfo),
address = res.Element("Address").Value.ToString(),
photoDesc = res.Element("PhotoDescription").Value.ToString(),
photoDir = XmlConvert.DecodeName(res.Element("Photos").Attribute("directory").Value.ToString()),
photoFiles = from a in doc.Descendants("Photos")
select new
{
photo = a.Element("PhotoFile").Value.ToString()
},
info = res.Element("InformationFile").Value.ToString()
};
foreach (var poi in pois)
{
IEnumerable<string> pF = (poi.photoFiles as IEnumerable<string>);
List<string> photoFiles = null;
if(pF != null)
photoFiles = pF.ToList<string>();
AddPushpin(poi.id, poi.name, poi.latitude, poi.longitude, poi.address, poi.photoDesc, poi.photoDir, photoFiles, poi.info);
};
I'm unsure about the part with the PhotoFiles because I get an unknown Object error when I try to read the Pushpin.
This what my Pushpin looks like:
public class MyPushpin : Pushpin
{
public int ID { get; set; }
public string Address { get; set; }
public string PhotoDesc { get; set; }
public string PhotoDir { get; set; }
public List<string> PhotoFiles { get; set; }
public MyPushpin() { }
public MyPushpin(int id, string name, double latitude, double longitude, string address, string photoDesc, string photoDir, List<string> photoFiles, string info)
{
Location loc = new Location(latitude, longitude);
this.ID = id;
this.Location = loc;
this.Name = name;
this.Address = address;
this.PhotoDesc = photoDesc;
this.PhotoDir = photoDir;
this.PhotoFiles = photoFiles;
this.Tag = info;
}
public void Update(string name , string photoDesc, List<string> photoFiles, string info)
{
this.Name = name;
this.PhotoDesc = photoDesc;
this.PhotoFiles = photoFiles;
this.Tag = info;
}
public override string ToString()
{
return String.Format("{0} - {1}", this.ID, this.Location, this.Address, this.PhotoDesc, this.PhotoDir, this.Tag);
}
And that's the code how I would like to use the file info in the custom Pushpin:
public partial class Gallery : ChildWindow
{
List<string> pics = null;
public Gallery(MyPushpin currentPin)
{
InitializeComponent();
pics = currentPin.PhotoFiles;
Loaded += (a, b) => {
LoadImages();
};
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
Close();
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
Close();
}
private void LoadImages()
{
List<Picture> coll = new List<Picture>();
pics.ForEach(delegate(String url)
{
coll.Add(AddPicture("url"));
});
//coll.Add(AddPicture("/pics/pic4poi_9000010-01.jpg"));
//coll.Add(AddPicture("/pics/pic4poi_9000010-02.jpg"));
//coll.Add(AddPicture("/pics/pic4poi_9000010-03.jpg"));
//coll.Add(AddPicture("/pics/pic4poi_9000010-04.jpg"));
Preview.Source = new BitmapImage(
new Uri(
"/pics/pic4poi_9000010-01.jpg",
UriKind.Relative));
lbImage.ItemsSource = coll;
}
private Picture AddPicture(string path)
{
return new Picture
{
Href = new BitmapImage(
new Uri(
path,
UriKind.Relative))
};
}
private void lbImage_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Preview.Source = ((Picture)lbImage.SelectedItem).Href;
}
}
public class Picture
{
public ImageSource Href { get; set; }
THX for your time
Chau

Could you please describe the problem that you are having in more detail. Have you debugged into it, where does it fail, what is the exception? What do you expect it to do.
Off the top of my head, this code looks wrong:
photoFiles = from a in doc.Descendants("Photos")
select new
{
photo = a.Element("PhotoFile").Value.ToString()
},
Replace doc with res, because you want the child elements of the current element, not of the document. Also you can use Elements here instead of Descendants since they are direct children. Also since there are multiple photo files, try a SelectMany (from a ... from b ...):
photoFiles = from a in res.Elements("Photos")
from b in a.Elements("PhotoFile")
select new
{
photo = b.Value.ToString()
},

Related

Related comboboxes, add a third combobox

I'm trying to do a related combobox. I already have 2 comboboxes, but now I want to add a third.
I have this code for the 2nd combo box.
I'm using windows forms.
The entire code: https://repl.it/#devilonline/MuddyPartialBytecode#main.cs
private string[] GetCastById(int id)
{
return nomes.Where(line => line.movies_id== id).Select(l => l.nomes).ToArray();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox1.Items.Clear();
int id = nomes[comboBox1.SelectedIndex].id;
foreach (string name1 in GetCastById(id))
{
this.comboBox1.Items.Add(name1);
}
}
print
It is obvious that you are clearing the Items of the comboBox1 then try to get the id of the selected item, which should throw an exception because no item will be selected by then:
comboBox1.Items.Clear(); // here the items are cleared
int id = nomes[comboBox1.SelectedIndex].id; // nomes[comboBox1.SelectedIndex] = -1
Based on your database, the cast table is related to the movies so each movie has a corresponding list of cast, you should then get the id of the selected movie rather than the selected nome:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox1.Items.Clear();
int id = movies[comboBoxMovie.SelectedIndex].id; // here we used comboBoxMovie
foreach (string name1 in GetCastById(id))
{
this.comboBox1.Items.Add(name1);
}
}
This is a great opportunity to use databinding through a System.ComponentModel.BindingList<>. Below is a working example. Note, I've added get methods inside the classes for simplicity of populating the ComboBoxes for this example.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
public class Form1
{
class Category
{
public int Id { get; set; }
public string Name { get; set; }
public Category(int id, string name)
{
this.Id = id;
this.Name = name;
}
public static List<Category> GetCategories()
{
return new List<Category>()
{
new Category(1, "Action"),
new Category(2, "Comedy")
};
}
}
class Movie
{
public int Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public Movie(int id, string name, int catId)
{
this.Id = id;
this.Name = name;
this.CategoryId = catId;
}
public static List<Movie> GetMovies()
{
return new List<Movie>()
{
new Movie(1, "Rambo", 1),
new Movie(2, "Delta Force", 1),
new Movie(3, "Elf", 2),
new Movie(4, "Space Balls", 2)
};
}
}
class Cast
{
public int Id { get; set; }
public string Names { get; set; }
public int MovieId { get; set; }
public Cast(int id, string names, int movieId)
{
this.Id = id;
this.Names = names;
this.MovieId = movieId;
}
public static List<Cast> GetCast()
{
return new List<Cast>()
{
new Cast(1, "Silvester Stalone", 1),
new Cast(2, "Chuck Norris", 2),
new Cast(3, "Will Farrell", 3),
new Cast(4, "John Candy", 4)
};
}
}
private BindingList<Category> _categoryBindingList = new BindingList<Category>();
private BindingList<Movie> _moviesBindingList = new BindingList<Movie>();
private BindingList<Cast> _castBindingList = new BindingList<Cast>();
private void Form1_Load(object sender, EventArgs e)
{
// Your database calls would replace these Get methods.
Category.GetCategories().ForEach(x => _categoryBindingList.Add(x));
Movie.GetMovies().ForEach(x => _moviesBindingList.Add(x));
Cast.GetCast().ForEach(x => _castBindingList.Add(x));
ComboBox1.DataSource = _categoryBindingList;
ComboBox1.DisplayMember = "Name";
ComboBox2.DataSource = _moviesBindingList.Where(x => x.CategoryId == (Category)ComboBox1.SelectedValue.Id).ToList();
ComboBox2.DisplayMember = "Name";
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
private void ComboBox1_SelectedValueChanged(object sender, EventArgs e)
{
ComboBox2.DataSource = _moviesBindingList.Where(x => x.CategoryId == (Category)ComboBox1.SelectedValue.Id).ToList();
ComboBox2.DisplayMember = "Name";
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
private void ComboBox2_SelectedValueChanged(object sender, EventArgs e)
{
ComboBox3.DataSource = _castBindingList.Where(x => x.MovieId == (Movie)ComboBox2.SelectedValue.Id).ToList();
ComboBox3.DisplayMember = "Names";
}
}

XML tests solve

I can't connect my XML file and my C# in microsoft visual studio. How do I solve this?
Here you find what need to be in your DA
public class LeegstaandXML
{
public string Index { get; set; }
public string Aard { get; set; }
public string Adres { get; set; }
public static int intElementsCount;
private List<LeegstaandXML> _leegstaand;
public List<LeegstaandXML> Lleegstaand
{
get
{
XmlDocument doc = new XmlDocument();
doc.Load("Lijst_leegstaande_bedrijfspanden.xml");
XmlNodeList elementlist = doc.GetElementsByTagName("fme:Lijst_leegstaande_bedrijfspanden");
intElementsCount = elementlist.Count;
_leegstaand = new List<LeegstaandXML>();
_leegstaand.Add(new LeegstaandXML()
{
Index = elementlist[Form1.counter]["fme:Dossier_ID"].InnerXml,
Adres = elementlist[Form1.counter]["fme:Adres"].InnerXml,
Aard = elementlist[Form1.counter]["fme:Aard_van_het_gebouw"].InnerXml,
});
return _leegstaand;
}
set
{
_leegstaand = value;
}
}
}
This is your connection in your form
private void btnVullen_Click(object sender, EventArgs e)
{
Leegstaand p = new Leegstaand();
do
{
counter++;
LeegstaandXML leegstaand2 = new LeegstaandXML();
foreach(LeegstaandXML lp in leegstaand2.Lleegstaand)
{
leegstaandDA NewItem = new leegstaandDA(lp.Index, lp.Adres, lp.Aard);
NewItem.AddItem();
//ListViewItem item = new ListViewItem(new string[] { lp.id.ToString(), lp.aard, lp.adres, lp.index.ToString() });
// item.Tag = lp;
//lsvLeegstaand.Items.Add(item);
}
} while (counter < LeegstaandXML.intElementsCount -1);
MessageBox.Show("implementatie is geslaagd");
counter = 0;
leegstaandDA.Getleegstaand();
foreach (Leegstaand l in leegstaandDA.Getleegstaand())
{
ListViewItem item = new ListViewItem(new string[] { l.index.ToString(), l.adres, l.aard});
item.Tag = l;
lsvLeegstaand.Items.Add(item);
}
}

Calling function on load of function

I'm trying to use my old code in my new application. I have the following problem.
I need to call something similar to this.Loaded += OnLoaded in my new code. But I cannot because I don't have : Page in my class.
The old code:
public sealed partial class VotePage : Page
{
public VotePage()
{
this.InitializeComponent();
// This will call the OnLoaded function
this.Loaded += OnLoaded;
}
Old code (OnLoaded function):
public async void OnLoaded(object sender, RoutedEventArgs e)
{
var response = await start();
dynamic dynJson = JsonConvert.DeserializeObject(response);
foreach (var item in dynJson)
{
Object votedGame = localSettings.Values[item.slug.ToString()];
string voted = "Collapsed";
string btnVoted = "VOTE";
bool btnEnabled = true;
if(votedGame != null)
{
voted = "Visible";
btnVoted = "VOTED!";
btnEnabled = false;
}
listofGames.Add(new Games { Title = item.name, Votes = item.votes, Slug = item.slug, Voted = voted, BtnVoted = btnVoted, BtnEnabled = btnEnabled });
}
gamesList.ItemsSource = listofGames;
}
New code:
public class GamesList
{
public List<Game> Games { get; set; }
public String Name { get; set; }
public GamesList(String databaseName)
{
Name = databaseName;
// This won't work because there is no await.
Games = DataService.GetGames;
}
DataService.GetGames function:
public async Task<List<Game>> GetGames()
{
Debug.WriteLine("GET for games.");
var response = await start();
dynamic dynJson = JsonConvert.DeserializeObject(response);
foreach (var item in dynJson)
{
Object votedGame = localSettings.Values[item.slug.ToString()];
string voted = "Collapsed";
string btnVoted = "VOTE";
bool btnEnabled = true;
if (votedGame != null)
{
voted = "Visible";
btnVoted = "VOTED!";
btnEnabled = false;
}
listofGames.Add(new Game { Title = item.name, Votes = item.votes, Slug = item.slug, Voted = voted, BtnVoted = btnVoted, BtnEnabled = btnEnabled });
}
return new List<Game>();
}
Depending on where, when and how the GamesList class is initialized you could give it a static creation method as suggested in the blog post linked by #Romasz:
public sealed class GamesList
{
public List<Game> Games { get; set; }
public String Name { get; set; }
private GamesList(String databaseName)
{
Name = databaseName;
}
public static async Task<GamesList> Create(string databaseName)
{
GamesList instance = new GamesList(databaseName);
instance.Games = await DataService.GetGames();
return instance
}
...
}
You will then use the factory method to create an instance of and initialize the class asynchronously:
public VotePage()
{
this.InitializeComponent();
this.Loaded += OnLoaded;
}
public async void OnLoaded(object sender, RoutedEventArgs e)
{
DataContext = await GamesList.Create("database name...");
}

EF Use values in WPF listbox

I Have one table of data:
tblFeed
Id
Title
Content
And I populated a Listbox in my WPF application with this table.
I have the issue now of using the Id value for an event but the Id keeps returning 0.
Any Suggestions?
WCF
public List<Feed> GetFeed()
{
List<Feed> r = new List<Feed>();
List<Feed> e;
using (TruckDb db = new TruckDb())
e = db.Feed.Where(x => x.Id != null).ToList();
foreach (var a in e)
{
var feed = new Feed()
{
Id = a.Id,
Title = a.Title,
Content = a.Content
};
r.Add(feed);
}
return r;
}
WPF
public async Task LoadFeeds()
{
TruckServiceClient TSC = new TruckServiceClient();
try
{
List<ClientItems> feeditems = new List<ClientItems>();
if (lbFeed.Items.Count <= 0)
foreach (var item in await TSC.GetFeedAsync())
{
feeditems.Add(new ClientItems
{
FId = item.Id,
FTitle = item.Title,
FContent = item.Content
});
}
lbFeed.ItemsSource = (feeditems.ToArray());
lbFeed.DisplayMemberPath = "FTitle";
}
catch (Exception)
{
throw;
}
}
public class ClientItems
{
public int FId { get; set; }
public string FTitle { get; set; }
public string FContent { get; set; }
public override string ToString()
{
return FTitle;
}
}
Delete Event
WCF
private void bnFeedDel_Click(object sender, RoutedEventArgs e)
{
TruckServiceClient service = new TruckServiceClient();
service.DelFeedAsync(new FeedView
{
Id = lbFeed.SelectedIndex
});
}
WPF
public void DelFeed(FeedView feedview)
{
using (var result = new TruckDb())
{
var t = new Feed
{
Id = feedview.Id
};
result.Feed.Remove(t);
result.SaveChanges();
}
}
In your bnFeedDel_Click method you are doing this:
Id = lbFeed.SelectedIndex
I think this is your problem as you don't want to set Id to a SelectedIndex value but rather:
[EDIT after some discussion]
Set SelectedValuePath inside LoadFeeds:
lbFeed.SelectedValuePath = "FId";
And use SelectedValue instead of SelectedIndex:
private void bnFeedDel_Click(object sender, RoutedEventArgs e)
{
TruckServiceClient service = new TruckServiceClient();
service.DelFeedAsync(new FeedView
{
// Of course you may want to check for nulls etc...
Id = (int)lbFeed.SelectedValue;
});
}
Also, you should use DbSet.Attatch() before deleting a record:
public void DelFeed(FeedView feedview)
{
using (var result = new TruckDb())
{
var t = new Feed
{
Id = feedview.Id
};
result.Feed.Attatch(t);
result.Feed.Remove(t);
result.SaveChanges();
}
}

How can i update a node of xml file on Windows 8 Metro style?

I will add a new node to parent node on my xml file. Unit test for this code says "success", it is passing but no added node in xml.
Also, some of tests i'm getting the error;
<< Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) >>
on the line SaveToFileAsync
what is wrong with me? and there is an alternative way to do this?
public string ConnectionPath { get; set; }
protected string XPath { get; set; }
protected string XParentPath { get; set; }
protected XmlDocument Source { get; set; }
protected StorageFolder SFolder { get; set; }
protected StorageFile SFile { get; set; }
public RepositoryBase(string connectionPath)
{
this.ConnectionPath = connectionPath;
}
public async void Insert(T entity)
{
SFolder = Package.Current.InstalledLocation;
SFile = await SFolder.GetFileAsync(this.ConnectionPath);
var content = await FileIO.ReadTextAsync(SFile);
if (!string.IsNullOrEmpty(content))
{
Source = new XmlDocument();
Source.LoadXml(content);
}
var tagName = typeof(T).Name;
if (tagName != null)
{
IXmlNode parentNode = Source.SelectSingleNode(XParentPath);
if (parentNode != null)
{
XmlElement newNode = Source.CreateElement(tagName);
newNode.InnerText = GetContent(entity);
parentNode.AppendChild(newNode);
}
}
await Source.SaveToFileAsync(SFile);
}
* PlaceRepositoryClass ;
public class PlaceRepository : RepositoryBase<Place>
{
public PlaceRepository()
: base("Data\\bla\\bla.xml")
{
XPath = "/Country[Id=1]/Cities/City[Id=1]/Places/Place";
XParentPath = "/Country[Id=1]/Cities/City[Id=1]/Places";
}
}
Unit Test Method ;
[TestMethod]
public void AppendNode()
{
Place place = new Place()
{
Id = 40,
Name = "xxxxx",
SummaryPath = "yyyyy",
Logo = "xy.png",
LogoSmall = "xy_small.png",
Latitude = "32.423",
Longitude = "34.23424",
Content = new PlaceContent() { Items = new List<ContentItem>() { new ContentItem() { TextPath = "aaaa", Header = "bbbbb", AudioFilePath = "x.mp3" } } },
Gallery = new PhotoGallery() { Photos = new List<Photo>() { new Photo() { Path = "ab.png", Text = "abab" } } }
};
PlaceRepository repository = new PlaceRepository();
repository.Insert(place);
}
You are trying to write to a file that's part of the application package, and that's read only. You could copy the file to local storage and make the modifications there perhaps.

Categories