Removing/Overwriting ListPicker items - c#

I've been struggling for the past 3 days with removing or overwriting ListPicker values. I want the click event of a button to remove the old list items and populate it with the new ones. I use LINQ to parse values from an XML file. The problem is that no matter what I try I always get an exception such as "Operation not supported on read-only collection." etc. Is there a way to remove all the values from the ListPicker?
Here's the code:
public partial class Visa : PhoneApplicationPage
{
List<Tiedot> vastausLista = new List<Tiedot>();
XDocument lista = XDocument.Load("Faktat.xml");
Random rand = new Random();
int piste = 0;
int levelStart = 1;
string level = string.Empty;
// Constructor
public Visa()
{
InitializeComponent();
tbPisteet.Text = string.Format("{0}/25", piste.ToString());
level = string.Format("level{0}", levelStart.ToString());
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (levelStart <= 1)
{
var documents =
(from docs in lista.Descendants("Taso")
where docs.Attribute("id").Value == level
select new
{
Elain = docs.Elements("vaihtoehto")
}).ToList();
foreach (var doc in documents)
{
foreach (var section in doc.Elain)
{
foreach (var item in section.Elements("vastaus"))
{
vastausLista.Add(new Tiedot { Elain = item.Value });
}
}
}
vaihtoehtoLista.ItemsSource = vastausLista;
var kuvaKysymys = (from tiedot in lista.Descendants("Taso")
where tiedot.Attribute("id").Value == level
select new Tiedot
{
Kuva = (string)tiedot.Element("kuva").Value,
Question = (string)tiedot.Element("kysymys").Value
}).FirstOrDefault();
BitmapImage kuvaKuva = new BitmapImage();
kuvaKuva.UriSource = new Uri(kuvaKysymys.Kuva, UriKind.Relative);
image.Source = kuvaKuva;
tbQuestion.Text = kuvaKysymys.Question;
}
base.OnNavigatedTo(e);
}
private void vaihtoehtoLista_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (vaihtoehtoLista.SelectedIndex == 1)
{
Update();
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
UpdateLevel();
}
public void Update()
{
piste++;
tbPisteet.Text = string.Format("{0}/25", piste.ToString());
MessageBox.Show("You're correct!!");
}
public void RemoveOldLevel()
{
while (vastausLista.Count > 0)
vaihtoehtoLista.Items.Remove(vastausLista[0]);
}
public void UpdateLevel()
{
levelStart++;
level = string.Format("level{0}", levelStart.ToString());
var documents =
(from docs in lista.Descendants("Taso")
where docs.Attribute("id").Value == level
select new
{
Elain = docs.Elements("vaihtoehto")
}).ToList();
foreach (var doc in documents)
{
foreach (var section in doc.Elain)
{
foreach (var item in section.Elements("vastaus"))
{
vastausLista.Add(new Tiedot { Elain = item.Value });
}
}
}
RemoveOldLevel();
vaihtoehtoLista.ItemsSource = vastausLista;
var kuvaKysymys = (from tiedot in lista.Descendants("Taso")
where tiedot.Attribute("id").Value == level
select new Tiedot
{
Kuva = (string)tiedot.Element("kuva").Value,
Question = (string)tiedot.Element("kysymys").Value
}).FirstOrDefault();
BitmapImage kuvaKuva = new BitmapImage();
kuvaKuva.UriSource = new Uri(kuvaKysymys.Kuva, UriKind.Relative);
image.Source = kuvaKuva;
tbQuestion.Text = kuvaKysymys.Question;
}
}

You have to use an ObservableCollection with your elements inside, as the DataContext of your ListPicker. Something like this:
ListPicker picker = new ListPicker();
ObservableCollection<Object> coll = your items inside;
picker.DataContext = coll;
And after you can modify directly the ObservableCollection. Or you can use:
ListPicker picker = new ListPicker();
picker.ItemsSource = List<> with your items;
But you have to reset the ItemSource each time you change the content of your List<>.

Related

How to interact with buttons created using a foreach loop?

I want these buttons created using a foreach loop from a list of items to access the information that is stored in these items.
I used a foreach loop to create buttons from a list of items that represent files in a directory and those items hold links to these files. My goal is to make pressing these buttons open a dialog with these files to write a line in them.
public List<mov.Movie> movies = new List<mov.Movie>() { };
private void writeReportToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (string file in Directory.EnumerateFiles(#"C:\Users\sloup\OneDrive\Desktop\MovieList", "*.txt"))
{
var lines = File.ReadAllLines(file);
string movieName = lines[0];
if (movies.Select(x => x.Name).Contains(movieName))
{
}
else
{
string movieLength = lines[1];
string movieYear = lines[2];
string movieReport = lines[3];
movies.Add(new mov.Movie(movieName, movieLength, movieYear, movieReport, #"C:\Users\sloup\OneDrive\Desktop\MovieList" + movieName + ".txt"));
}
}
int X = 1;
int Y = 1;
foreach (var movie in movies)
{
var movie1Button = new Button();
movie1Button.Text = movie.Name;
movie1Button.Font = new Font("Calibri", 12);
movie1Button.ForeColor = Color.Black;
movie1Button.Padding = new Padding(6);
movie1Button.AutoSize = true;
this.Controls.Add(movie1Button);
movie1Button.Location = new System.Drawing.Point(20, 50 * X);
X++;
movie1Button.Click += Movie1Button_Click;
var movie1Label = new Label();
movie1Label.Text = movie.Year;
movie1Label.Font = new Font("Calibri", 12);
movie1Label.ForeColor = Color.Black;
movie1Label.Padding = new Padding(6);
movie1Label.AutoSize = true;
this.Controls.Add(movie1Label);
movie1Label.Location = new System.Drawing.Point(200, 50 * Y);
Y++;
}
}
private void Movie1Button_Click(object? sender, EventArgs e)
{
string[] lines1 = File.ReadAllLines();
var lines = File.ReadAllLines();
string movieName = lines[0];
string movieLength = lines[1];
string movieYear = lines[2];
}
public class Movie
{
public string Name;
public string Length;
public string Year;
public string Report;
public string Link;
public Movie(string movieName, string movieLength, string movieYear, string movieReport, string movieLink)
{
Name = movieName;
Length = movieLength;
Year = movieYear;
Report = movieReport;
Link = movieLink;
}
}
You can use the Tag property to attach the movie object to each button in the loop:
movie1Button.Tag = movie;
afterwards in the click event grab the button from the sender and cast the Tag-object back to a Movie
private void Movie1Button_Click(object? sender, EventArgs e)
{
Button button = sender as Button
(if button != null)
{
Movie movie = button.Tag as Movie;
// do what ever you like afterwards
}
}

My C# WPF webscraper returns error when more than one result is found

I am working on a WPF XAML application that scrapes certain websites for products. I have the search part working and it finds what I'm looking for. But as soon as there is more then 1 result I get a System.InvalidoperationException. I use a ObservableCollection to put the results into a <ListBox>.
Here is the search method:
private static ObservableCollection<EntryModel> _entries = new ObservableCollection<EntryModel>();
public static ObservableCollection<EntryModel> LoadCollectionData
{
get { return _entries; }
set { _entries = value; }
}
public static void PrehmSearchResults(string SearchQuery)
{
HtmlWeb web = new HtmlWeb();
try
{
string ZoekOpdracht = SearchQuery.Replace(" ", "+");
HtmlDocument doc = web.Load("https://www.prehmshop.de/advanced_search_result.php?keywords=" + ZoekOpdracht);
var title = doc.DocumentNode.CssSelect("div.header_cell > a").Single().InnerText;
var links = doc.DocumentNode.CssSelect("a.product_link");
var productLink = new List<string>();
var productTitle = new List<string>();
foreach (var item in links)
{
if (item.Attributes["href"].Value.Contains(".html"))
{
productLink.Add(item.Attributes["href"].Value);
productTitle.Add(title);
}
}
var TitleAndLink = productLink.Zip(productTitle, (l, t) => new { productLink = l, productTitle = t });
foreach (var nw in TitleAndLink)
{
var product = new List<EntryModel>();
var adDetails = new EntryModel
{
Title = nw.productTitle,
Link = nw.productLink
};
Debug.Print(adDetails.ToString());
var ZoekOpdrachtInTitle = adDetails.Title.ToLower().Contains(ZoekOpdracht.ToLower());
if (ZoekOpdrachtInTitle)
{
_entries.Add(adDetails);
}
}
}
So I found the solution without changing too much code. thanks for the help from #PaulSinnema.
The link is part of the title so I only had to change
var title = doc.DocumentNode.CssSelect("div.header_cell > a").ToList();
And I had to change the foreach loop:
foreach (var item in title)
{
if (item.Attributes["href"].Value.Contains(".html"))
{
productLink.Add(item.Attributes["href"].Value);
productTitle.Add(item.InnerText);
}
}

Windows Phone 7 Gif to Png

I am building an Rss reader app and having problems with gifs.
Does anyone know how to build the ImageConverter class so it would convert gif to png?
Converting gifs in code will also work for me.
My app works in a way that it takes everything from the feed, puts it in a list() first and then it populates the listbox, (in a way the user chooses to). gifs leave blank images :(
so basically converter would have to work with a link, not a direct data stream.
I will add some code on how my data is updated:
ObservableCollection<FeedItem> slika0; //where the feeditems from the selected category go
public ObservableCollection<FeedItem> Slika0
{
get { return slika0; }
set
{
slika0 = value;
OnPropertyChanged("Slika0");
}
}
int broj_elemenata = 0;
bool nema_elemenata = false;
private void UpdateFeedList(string feedXML)
{
StringReader stringReader = new StringReader(feedXML);
XmlReader xmlReader = XmlReader.Create(stringReader);
SyndicationFeed feed = SyndicationFeed.Load(xmlReader);
List<string> kategorije = new List<string>();
foreach (SyndicationItem sitem in feed.Items)
{
foreach (SyndicationCategory sc in feed.Categories)
{
if (!kategorije.Contains(sc.Name))
{
kategorije.Add(sc.Name);
}
}
}
FeedItem FeedItem = new FeedItem();
Slika0 = new ObservableCollection<FeedItem>();
//SyndicationCategory tražena_kat = new SyndicationCategory("Trendy");
foreach (SyndicationItem item in feed.Items)
{
foreach (SyndicationCategory sc in item.Categories)
{
FeedItem.Content_List.Add(sc.Name);
foreach (SyndicationElementExtension ext in item.ElementExtensions)
{
XElement ele = ext.GetObject<XElement>();
if (ele.Name.LocalName == "encoded" && ele.Name.Namespace.ToString().Contains("content"))
{
FeedItem.Content_List.Add(item.Title.Text);
FeedItem.Content_List.Add(ele.Value);//takes the content of the feed
}
}
foreach (SyndicationLink link in item.Links)
{
FeedItem.Content_List.Add(link.Uri.AbsoluteUri); //takes the links for browsing and the image
}
}
}
IsolatedStorageSettings.ApplicationSettings["ContentList"] = FeedItem.Content_List;
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
int i;
int x = 0;
Slika0.Clear();
foreach (var item in FeedItem.Content_List)
{
i = FeedItem.Content_List.IndexOf(item, x); //x = index of category in the list
if (item == "Trendy")
{
FeedItem FF = new FeedItem();
FF.Post_text = FeedItem.Content_List[i + 1];//title of article
FF.Content_link = FeedItem.Content_List[i + 2];//content
FF.Post_link = FeedItem.Content_List[i + 3];//the location of link for browsing
FF.Post_slika = FeedItem.Content_List[i + 4]; //location of image link
if (FF.Post_slika == "") //if there is no link for picture code is executed
{
FF.Post_slika = "Slike/zimo_veliki_tile.png";
}
Slika0.Add(FF);
this.lsSlika_P.ItemsSource = Slika0; //take
x = i + 5;
broj_elemenata++;
}
}
if (lsSlika_P.Items.Count <= 3)
{
scroll_panorama.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
}
if (lsSlika_P.Items.Count == 0)
{
nema_elemenata = true;
}
else nema_elemenata = false;
});
pan_progres.Visibility = Visibility.Collapsed;//progress bar
}

XDocument reference issue c#

I have these 2 methods wrote in another class, but how can I reach the output off this from other classes? I wan't just the value of lsTags.
That's my code:
private void LoadXMLFile()
{
WebClient xmlClient = new WebClient();
xmlClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(XMLFileLoaded);
xmlClient.DownloadStringAsync(new Uri("codeFragments.xml", UriKind.RelativeOrAbsolute));
}
private void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
string xmlData = e.Result;
XDocument xDoc = XDocument.Parse(xmlData);
var tagsXml = from c in xDoc.Descendants("Tag") select c.Attribute("name");
foreach (string tagName in tagsXml)
{
Tag oTag = new Tag();
oTag.name = tagName;
var tags = from d in xDoc.Descendants("Tag")
where d.Attribute("name").Value == tagName
select d.Elements("oFragments");
var tagXml = tags.ToArray()[0];
foreach (var tag in tagXml)
{
CodeFragments oFragments = new CodeFragments();
oFragments.tagURL = tag.Attribute("tagURL").Value;
//Tags.tags.Add(oFragments);
oTag.lsTags.Add(oFragments);
}
this.lsTags.Add(oTag);
}
}
}
Silverlight does not support XmlDocument. Use LINQ to XML instead.

A Problem in DataGridView : datagridview seems readonly to user (WinForms)

I have a datagridview in my form. It fills by selecting country with cities of country.I have set the property (AllowUsersToAddRow = True)
but when i run my project user can't add or edit or delete any row.I checked it.It is not readonly(readonly = false) and It is enable (Enabled = true)
What's the problem?
Code of fill datagridview:
private void cmbCountryValues_SelectedIndexChanged(object sender, EventArgs e)
{
dgvCityValues.Enabled = cmbCountryValues.SelectedIndex>=0;
if (!dgvCityValues.Enabled)
{
dgvCityValues.DataSource = null;
return;
}
int CountryId = int.Parse(cmbCountryValues.SelectedValue.ToString());
dgvValues.DataSource = from record in Program.dal.Cities(CountryId) select new { record.City};
}
If you find this question useful don't forgot to vote it.
To give a simplified example, if I do the equivalent of your query, such as:
var cities = new City[] { new City("New York","NY"), new City("Sydney","SY"), new City("London","LN") };
dataGridView.DataSource = cities;
I get the same result as you - no option to add new rows, but if I change to BindingList<T> and set this to AllowNew it all works:
var cities = new City[] { new City("New York","NY"), new City("Sydney","SY"), new City("London","LN") };
var citiesBinding = new BindingList<City>(cities);
citiesBinding.AllowNew = true;
dataGridView.DataSource = citiesBinding;
EDIT - with a solution for your particular example:
private class City
{
public string Name { get; set; }
}
private void cmbCountryValues_SelectedIndexChanged(object sender, EventArgs e)
{
dgvCityValues.Enabled = cmbCountryValues.SelectedIndex >= 0;
if (!dgvCityValues.Enabled)
{
dgvCityValues.DataSource = null;
return;
}
int CountryId = int.Parse(cmbCountryValues.SelectedValue.ToString());
var queryResults = from record in Program.dal.Cities(CountryId) select new City { Name = record.City };
var queryBinding = new BindingList<City>(queryResults.ToList());
queryBinding.AllowNew = true;
dgvValues.DataSource = queryBinding;
}
Note that a) I had to change the anonymous type in the query select into a concrete type City and also change the IEnumerable<T> returned by Linq query to an IList<T> compatible type to create the BindingList<T>. This should work, however :)

Categories

Resources