Im working on a simple project. I have windows form and when the Form open I want my "Userslistview" with 3 Columns to be filled with data from my XML which is also created by the program.
I have tried a couple of methodes but the listview just stays empty.
So here's the Load event code im using
private void MainMenu_Load(object sender, EventArgs e)
{
string xmlfile = AppDomain.CurrentDomain.BaseDirectory + "Users.xml";
if (!File.Exists(xmlfile))
{
return;
}
UserslistView.View = View.Details;
UserslistView.GridLines = true;
UserslistView.Sorting = SortOrder.Descending;
UserslistView.FullRowSelect = true;
UserslistView.Columns.Add("Active", 80);
UserslistView.Columns.Add("username", 120);
UserslistView.Columns.Add("Last Logon", 120);
UserslistView.Items.Clear();
DataSet ds = new DataSet();
ds.ReadXml(xmlfile);
ListViewItem item;
foreach (DataRow dr in ds.Tables["user"].Rows)
{
item = new ListViewItem(new string[]
{
dr["username"].ToString(),
dr["USERID"].ToString(),
dr["lastlogon"].ToString()
});
UserslistView.Items.Add(item);
}
}
and here's the XMl im using
UPDATE 1
I swapped my code for this.
private void MainMenu_Load(object sender, EventArgs e)
{
UserslistView.View = View.Details;
UserslistView.GridLines = true;
UserslistView.FullRowSelect = true;
UserslistView.Columns.Add("Active", 100);
UserslistView.Columns.Add("username", 120);
//UserslistView.Columns.Add("Last Logon", 100);
string xmlfile = AppDomain.CurrentDomain.BaseDirectory + "Users.xml";
XmlDocument doc = new XmlDocument();
try
{
doc.Load(xmlfile);
foreach (XmlNode n in doc.SelectNodes("/Users//user"))
{
ListViewItem li = new ListViewItem(n.SelectSingleNode("username").InnerText);
li.SubItems.Add(n.SelectSingleNode("lastlogon").InnerText);
UserslistView.Items.Add(li);
}
}
catch { }
}
The count for the node is 2.
But listview still stays empty
First make sure your xml is available in your project. I followed this example: How to add an xml file as a resource to Windows Forms exe
using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;
private void MainMenu_Load(object sender, EventArgs e)
{
UserslistView.View = View.Details;
UserslistView.GridLines = true;
UserslistView.Sorting = SortOrder.Descending;
UserslistView.Columns.Add("Active", 80);
UserslistView.Columns.Add("username", 120);
UserslistView.Columns.Add("Last Logon", 120);
UserslistView.Items.Clear();
var doc = XDocument.Parse(Properties.Resources.Users);
var output = from x in doc.Root.Elements("user")
select new ListViewItem(new []
{
x.Element("USERID").Value,
x.Element("username").Value,
x.Element("lastlogon").Value
});
UserslistView.Items.AddRange(output.ToArray());
}
}
You can use XDocument and parse your Xml
XDocument doc = XDocument.Load(file path);
var nodes = doc.Descendants("user").Select(e=> new ListViewItem( new [] {
e.Element("username").Value,
e.Element("USERID").Value,
//e.Element("password").Value,
e.Element("lastlogon").Value
})).ToArray();
UserslistView.Items.AddRange(nodes);
Related
There is a form in which there are text lines, and a flowLayotpanel for accepting dynamically created pictureboxes, please tell me the code for implementing the transfer of images (in this case, from 1 to 3 pieces) to the MS WORD template For text, the transfer is implemented, I can not find a suitable solution for images
example code like this
using DirectShowLib;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using Word = Microsoft.Office.Interop.Word;
private readonly string TemplateFileName = #"D:\BASE\1.docx";
private void btn_scrennshot_Click(object sender, EventArgs e)
{
try
{
if (!Directory.Exists(#"D:\BASE\Images"))
{
Directory.CreateDirectory(#"D:\BASE\Images");
MessageBox.Show("OK");
}
else
{
string path = #"D:\BASE\Images";
pictureBox1.Image.Save(path + #"\" + textBox_3.Text + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + ".jpeg", ImageFormat.Jpeg);
}
var panel = new TableLayoutPanel();
panel.AutoSize = true;
Mat m = new Mat();
capture.Retrieve(m);
var pb = new PictureBox();
pb.Image = new Bitmap(m.ToImage<Bgr, byte>().Flip(Emgu.CV.CvEnum.FlipType.None).Bitmap);
pb.SizeMode = PictureBoxSizeMode.Zoom;
pb.Name = $"SMV_{textBox_3.Text + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second}";
pb.Height = pb.Image.Height / 10;
pb.Width = pb.Image.Width / 10;
var name = new Label();
name.Text = $"SMV_{textBox_3.Text + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second}";
var exportimage_btn = new Button();
exportimage_btn.Text = "Select";
exportimage_btn.Click += Exportimage_btn_Click;
var deleteimage_btn = new Button();
deleteimage_btn.Text = "Delete";
deleteimage_btn.Click += Deleteimage_btn_Click;
panel.Controls.Add(pb);
panel.Controls.Add(name);
panel.Controls.Add(exportimage_btn);
panel.Controls.Add(deleteimage_btn);
flowLayoutPanel1.Controls.Add(panel);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void Deleteimage_btn_Click(object sender, EventArgs e)
{
var deleteButton = (Button)sender;
var tableLayoutPanel = deleteButton.Parent;
var flowLayoutPanel1 = tableLayoutPanel.Parent;
flowLayoutPanel1.Controls.Remove(tableLayoutPanel);
foreach (Control control in tableLayoutPanel.Controls)
control.Dispose();
tableLayoutPanel.Dispose();
}
private void Exportimage_btn_Click(object sender, EventArgs e)
{
var exportButton = (Button)sender;
var tableLayoutPanel = exportButton.Parent;
tableLayoutPanel.Controls.Remove(exportButton);
flowLayoutPanel_images.Controls.Add(tableLayoutPanel);
exportButton.Dispose();
}
private void btn_close_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void btn_export_Click(object sender, EventArgs e)
{
var text1 = textBox_2.Text;
var text2 = textBox_2.Text;
var text3 = textBox_3.Text;
var text4 = textBox_4.Text;
var data1 = dateTimePicker_1.Value.ToShortDateString();
var data2 = dateTimePicker_2.Value.ToShortDateString();
var text5 = textBox_5.Text;
var text6 = textBox_6.Text;
var text7 = comboBox_1.Text;
var text8 = comboBox_2.Text;
var text9 = comboBox_3.Text;
var text10 = comboBox_4.Text;
var text11 = textBox_7.Text;
var text12 = textBox_8.Text;
var text13 = comboBox_5.Text;
var text14 = textBox_9.Text;
//TODO WORD
var wordApp = new Word.Application();
wordApp.Visible = false;
try
{
var wordDocument = wordApp.Documents.Open(TemplateFileName);
ReplaceWordStub("{text1}", text1, wordDocument);
ReplaceWordStub("{text2}", text2, wordDocument);
ReplaceWordStub("{text3}", text3, wordDocument);
ReplaceWordStub("{text4}", text4, wordDocument);
ReplaceWordStub("{data1}", data1 wordDocument);
ReplaceWordStub("{text5}", text5, wordDocument);
ReplaceWordStub("{data2}", data2, wordDocument);
ReplaceWordStub("{text6}", text6, wordDocument);
ReplaceWordStub("{text7}", text7, wordDocument);
ReplaceWordStub("{text8}", text8, wordDocument);
ReplaceWordStub("{text9}", text9, wordDocument);
ReplaceWordStub("{text10}", text10, wordDocument);
ReplaceWordStub("{text11}", text11, wordDocument);
ReplaceWordStub("{text12}", text12, wordDocument);
ReplaceWordStub("{text13}", text13, wordDocument);
ReplaceWordStub("{text14}", text14, wordDocument);
wordDocument.SaveAs2(#"D:\BASE\2.docx");
wordApp.Visible = true;
}
catch
{
MessageBox.Show("Error!");
}
}
private void ReplaceWordStub(string stubToReplace, string text, Word.Document wordDocument)
{
var range = wordDocument.Content;
range.Find.ClearFormatting();
range.Find.Execute(FindText: stubToReplace, ReplaceWith: text);
}
Because I don't have a camera, I use an existing picture to add. Then add it and save it to the folder at the same time, keeping the picture name consistent.
You can modify it according to your actual situation, I'm just doing it as a demonstration.
If you have questions about my code, please add a comment below.
First, add a bookmark in the template:
Use selection to find the bookmark position and start importing pictures.
bk.Select();
Selection sel = wordApp.Selection;
sel.InlineShapes.AddPicture("//path");
Export code:
private void btn_export_Click(object sender, EventArgs e) {
//TODO WORD
var wordApp = new Word.Application();
wordApp.Visible = false;
try {
var wordDocument = wordApp.Documents.Open(TemplateFileName);
//Through the Applicatin property of Document, we can get the Applicatin object in turn.
wordApp = wordDocument.Application;
wordDocument.ActiveWindow.Visible = true;
foreach (Bookmark bk in wordDocument.Bookmarks) {
if (bk.Name == "picture") {
//Use the Selection object to insert a picture
bk.Select();
Selection sel = wordApp.Selection;
//Traverse the big panel to find all the small panels
foreach (Control img in flowLayoutPanel_images.Controls) {
//Traverse the small panel to find the label
foreach (Control label in img.Controls) {
if (label is Label)
//Determine the picture to be added from the folder according to the text of the label
sel.InlineShapes.AddPicture(#"C:/demo/images/" + label.Text + ".png");
}
}
}
}
wordDocument.SaveAs(#"C:/demo/images/2.docx");
wordApp.Quit();
} catch {
MessageBox.Show("Error!");
}
}
Schematic diagram:
word:
app:
Start:
Output:
After:
Every time when I click the button only one row will be displayed. But it should show multiple rows. I declare the list after the constructor invoke. I tried with gridview.update() and gridview.refresh() but they didn't work. I could not findout the issue.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using JournalEntryApp.Model;
namespace JournalEntryApp
{
public partial class NewDocument : Form
{
public NewDocument()
{
InitializeComponent();
}
List<JEFrom> JEFromsList = new List<JEFrom>();
List<JETo> JETosList = new List<JETo>();
JEFrom _jef = null;
private void NewDocument_Load(object sender, EventArgs e)
{
label4.Text = DateTime.Now.ToString("dd-MMM-yyyy");
using (var db =new JournalContext())
{
unitComboBox.DataSource = db.Units.ToList();
unitComboBox.ValueMember = "Id";
unitComboBox.DisplayMember = "UnitName";
}
}
private void addToListButton_Click(object sender, EventArgs e)
{
if (string.Empty== fromAccountTextBox.Text)
{
MessageBox.Show("From Account can not be empty!!!");
}
else if (string.Empty == toAccountTextBox.Text)
{
MessageBox.Show("To Account can not be empty!!!");
}
else
{
_jef = new JEFrom{ FromEntryName= fromAccountTextBox.Text , FromEntryDate= DateTime.Now };
JEFromsList.Add(_jef);
temporaryDataGridView.DataSource = JEFromsList;
fromAccountTextBox.Text = string.Empty;
toAccountTextBox.Text = string.Empty;
}
}
}
}
The temporaryDataGridView cannot detect that you have changed the DataSource. It will only refresh when Datasource has changed.
temporaryDataGridView.DataSource = null;
temporaryDataGridView.DataSource = JEFromsList;
so change the Datasource null first.
Or you can use bindingSource
private void NewDocument_Load(object sender, EventArgs e)
{
this.bindingSource1.DataSource = JEFromsList;
temporaryDataGridView.DataSource = this.bindingSource1;
label4.Text = DateTime.Now.ToString("dd-MMM-yyyy");
using (var db =new JournalContext())
{
unitComboBox.DataSource = db.Units.ToList();
unitComboBox.ValueMember = "Id";
unitComboBox.DisplayMember = "UnitName";
}
}
in button_click
JEFromsList.Add(_jef);
bindingSource1.ResetBindings(true);
First post on this wonderful site so feedback is greatly appreciated.
I followed a video instruction on Youtube by one of the NAV guru about consuming web services using C#. I was able to replicate what he did in Sandbox, but now that I want to implement in Live it's a hit or miss type of ordeal. If I made a small change somewhere the WS stopped working then after tweaking it here and there all of a sudden it works, then the cycle continues.
I basically created a form with two datagrids, one for sales header and one for sales line, with 3 buttons for New Order, New Line, and Save. Below is my code. Can you point me in the right direction as to:
1. Why my code is not working?
2. Why it works and then stops working? What to watch out for?
3. In my original code, using System.Data is not showing an error. I had to comment it out on this form because it has the scribbly line underneath. How come?
I am a noob to web services and C# in general. Thanks in advance for your help.
using System;
using System.Collections.Generic;
using System.ComponentModel;
//using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SalesOrderXML.ServiceReference3;
using System.ServiceModel;
using System.Net;
namespace SalesOrderXML
{
public partial class Form2 : Form
{
private Sales saleslive = new Sales();
private SalesOrderService_PortClient svc1;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
//BasicHttpBinding SalesOrderService_Binding = new BasicHttpBinding();
//SalesOrderService_Binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
//SalesOrderService_Binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
var binding = new System.ServiceModel.BasicHttpBinding();
binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
svc1 = new SalesOrderService_PortClient(
//SalesOrderService_Binding, new EndpointAddress("http://localhost:7047/DynamicsNAV/WS/Cronus%20-%20LIVE%20COMPANY/Codeunit/SalesOrderService"));
binding, new EndpointAddress("http://localhost:7047/DynamicsNAV/WS/Cronus%20-%20LIVE%20COMPANY/Codeunit/SalesOrderService"));
svc1.ClientCredentials.Windows.ClientCredential = new NetworkCredential("testuser", "password123", "localhost");
svc1.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
//SalesOrderService_Binding.MaxReceivedMessageSize = 99999999;
binding.MaxReceivedMessageSize = 99999999;
binding.MaxBufferSize = 99999999;
saleslive = new Sales();
LoadData();
}
private void dataGridView3_RowEnter(object sender, DataGridViewCellEventArgs e)
{
var orderlive = saleslive.Order[e.RowIndex];
dataGridView4.DataSource = orderlive.Line;
}
private void LoadData()
{
svc1.ReadSalesOrders(ref saleslive);
dataGridView3.DataSource = saleslive.Order;
}
private void SaveData()
{
svc1.SaveSalesOrders(saleslive);
//dataGridview3.DataSource = saleslive.Order;
}
private void button3_Click(object sender, EventArgs e)
{
svc1.SaveSalesOrders(saleslive);
LoadData();
}
private void button1_Click(object sender, EventArgs e)
{
var orderlive = saleslive.Order;
orderlive[orderlive.Count() - 1] = new Order { Line = new Line[] { } };
Array.Resize(ref orderlive, saleslive.Order.Count() + 1);
saleslive.Order = orderlive;
dataGridView3.DataSource = saleslive.Order;
}
private void dataGridView4_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var orderlive = saleslive.Order[dataGridView3.CurrentRow.Index];
var line = orderlive.Line;
if (line == null)
{
line = new Line[] { };
}
Array.Resize(ref line, line.Count() + 1);
line[line.Count() - 1] = new Line
{
LineDocType = "Order",
LineDocNo = "",
LineNo = (line.Count() * 10000).ToString(),
Type = "Item",
SKU = "0316",
Quantity = "10",
Price = "1200",
Amount = "12000",
LineTotal = "12000"
};
orderlive.Line = line;
dataGridView4.DataSource = line;
}
}
}
Im at beginner level and have tried for a while now. Im trying to remove an item from a ListBox with the help of a remove button. The code is not giving away any errors but the items is not disappearing from the list.
This is the part im struggling with
void taBort()
{
listboxKontakter.SelectedItems.Remove(listboxKontakter.SelectedItems);
textboxAnteckningar.Clear();
textboxGatuadress.Clear();
textboxNamn.Clear();
textboxPostnummerOrt.Clear();
textboxEmail.Clear();
textboxFödelsedag.Value = DateTime.Now;
}
Here is my entire code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace adressboken
{
public partial class Form1 : Form
{
List<Kontakter> kontaktLista = new List<Kontakter>();
Kontakter person;
string path = "kontakter.txt";
public Form1()
{
InitializeComponent();
}
private void LäggTill_Click(object sender, EventArgs e)
{
person = new Kontakter();
person.FullständigtNamn = textboxNamn.Text;
person.Gatuadress = textboxGatuadress.Text;
person.PostnummerOrt = textboxPostnummerOrt.Text;
person.Födelsedag = textboxFödelsedag.Value;
person.Email = textboxEmail.Text;
person.Anteckningar = textboxAnteckningar.Text;
kontaktLista.Add(person);
listboxKontakter.DataSource = null;
listboxKontakter.DisplayMember = "FullständigtNamn";
listboxKontakter.DataSource = kontaktLista;
textboxAnteckningar.Clear();
textboxGatuadress.Clear();
textboxNamn.Clear();
textboxPostnummerOrt.Clear();
textboxEmail.Clear();
textboxFödelsedag.Value = DateTime.Now;
textboxAntal.Text = kontaktLista.Count.ToString();
}
private void Rensa_Click(object sender, EventArgs e)
{
textboxAnteckningar.Clear();
textboxGatuadress.Clear();
textboxNamn.Clear();
textboxPostnummerOrt.Clear();
textboxEmail.Clear();
textboxFödelsedag.Value = DateTime.Now;
}
void taBort()
{
textboxAnteckningar.Clear();
textboxGatuadress.Clear();
textboxNamn.Clear();
textboxPostnummerOrt.Clear();
textboxEmail.Clear();
textboxFödelsedag.Value = DateTime.Now;
}
private void Form1_Load(object sender, EventArgs e)
{
kontaktLista = new List<Kontakter>();
string line = "";
StreamReader sr = new StreamReader(path);
while ((line = sr.ReadLine()) != null)
{
string[] listarray = line.Split(',');
person = new Kontakter();
person.FullständigtNamn = listarray[0];
person.Gatuadress = listarray[1];
person.PostnummerOrt = listarray[2];
person.Email = listarray[3];
person.Födelsedag = Convert.ToDateTime(listarray[4]);
person.Anteckningar = listarray[5];
kontaktLista.Add(person);
}
sr.Close();
listboxKontakter.DataSource = kontaktLista;
listboxKontakter.DisplayMember = "FullständigtNamn";
}
public void listboxKontakter_Click(object sender, EventArgs e)
{
person = (Kontakter)listboxKontakter.SelectedItem;
textboxNamn.Text = person.FullständigtNamn;
textboxGatuadress.Text = person.Gatuadress;
textboxPostnummerOrt.Text = person.PostnummerOrt;
textboxEmail.Text = person.Email;
textboxFödelsedag.Value = person.Födelsedag;
var selectedindex = listboxKontakter.SelectedItems;
}
private void Spara_Click(object sender, EventArgs e)
{
StreamWriter sw = new StreamWriter(path);
foreach (Kontakter k in kontaktLista)
{
sw.WriteLine(k.FullInfo);
}
sw.Close();
}
private void taBortToolStripMenuItem_Click(object sender, EventArgs e)
{
taBort();
}
private void TaBort_Click(object sender, EventArgs e)
{
taBort();
}
}
}
Your code seems to remove all selected items, and does not refresh.
How about:
listboxKontakter.SelectedItems.Remove(listboxKontakter.SelectedItem);
listboxKontakter.Refresh();
You remove only the single selected item, then refresh your listbox.
If you want to remove ALL items try:
listboxKontakter.Items.Clear();
If you use a DataSource try:
listboxKontakter.DataSource = null;
If all else fails you could loop through the collection and RemoveAt:
for(int i=listboxKontakter.Items.Count; i > -1; i--) {
{
listboxKontakter.Items.RemoveAt(i);
}
Based on a bit of chatting, this should work for you:
void taBort()
{
var newList = (List<Kontakter>)listboxKontakter.DataSource;
var ds = newList.Where(k => k.FullständigtNamn != ((Kontakter)listboxKontakter.SelectedItem).FullständigtNamn).ToList();
listboxKontakter.DataSource = ds;
listboxKontakter.DisplayMember = "FullständigtNamn";
textboxAnteckningar.Clear();
textboxGatuadress.Clear();
textboxNamn.Clear();
textboxPostnummerOrt.Clear();
textboxEmail.Clear();
textboxFödelsedag.Value = DateTime.Now;
}
If you want to remove several items at once try:
var ds = newList.Where(k => !listboxKontakter.SelectedItems.Contains(k.FullständigtNamn)).ToList();
How about:
listboxKontakter.Items.Remove(itemthatneedstoberemoved)
and
listboxKontakter.Items.Clear();
(I assume you called the listbox, listboxKontakter?)
:
Take a look at this
.SelectedItems is basically just an array list of what items you have selected, so you will need to access those like this .SelectedItems[0] .SelectedItems[1].
However the above code even with the [0], [1] will only remove them from the selected list not the actual list box.
If you want to remove them from the list box you need to use the .Items.Remove call.
while(listboxKontakter.SelectedItems.Count >0)
{
listboxKontakter.Items.Remove(listboxKontakter.SelectedItems[0]);
}
EDIT:
If it is a single select listbox all you have to do is
listboxKontakter.Items.Remove(listboxKontakter.SelectedItem);
I want to make a RSS reader which makes it possible to get multiple news feeds at the same time, without my application "freezing" while getting the feed. To do this, I want some of the code to run in a seperate thread. I have tried some different things, to make it run in a seperate thread, but I keep getting exceptions. My code looks like this atm:
namespace NewsReader
{
public partial class Form1 : Form
{
XmlTextReader rssReader;
XmlDocument rssDoc;
XmlNode nodeRss;
XmlNode nodeChannel;
XmlNode nodeItem;
ListViewItem rowNews;
public Form1()
{
InitializeComponent();
}
private void btnRead_Click(object sender, EventArgs e)
{
//Creates a XmlTextReader which reads from the url entered in input field
rssReader = new XmlTextReader(txtUrl.Text);
//Creates an xml doc to save the content of the entered path
rssDoc = new XmlDocument();
//Loads the xml content from the reader into a XmlDocument
rssDoc.Load(rssReader);
//Make a loop to search for the <rss> tag
for (int i = 0; i < rssDoc.ChildNodes.Count; i++)
{
//If the childenode is the rss tag
if (rssDoc.ChildNodes[i].Name == "rss")
{
//the <rss> tag is found, and we know where it is
nodeRss = rssDoc.ChildNodes[i];
}
}
//Make a loop to search for the <channel> tag
for (int i = 0; i < nodeRss.ChildNodes.Count; i++)
{
//If the childnode is the channel tag
if (nodeRss.ChildNodes[i].Name == "channel")
{
//The channel tag is found and we know where it is
nodeChannel = nodeRss.ChildNodes[i];
}
}
//Make a loop to search for the <item> tag
for (int i = 0; i < nodeChannel.ChildNodes.Count; i++)
{
//If the childnode is the item tag
if (nodeChannel.ChildNodes[i].Name == "item")
{
//the item tag is found, and we know where it is
nodeItem = nodeChannel.ChildNodes[i];
//Creates a new row in the LstView which contains information from inside the nodes
rowNews = new ListViewItem();
rowNews.Text = nodeItem["title"].InnerText;
rowNews.SubItems.Add(nodeItem["link"].InnerText);
lstView.Items.Add(rowNews);
}
}
}
}
}
Does anyone have some examples of how to handle this problem? Code examples with my code is very appreciated :)
Thanks in advance.
You may checkout the BackgroundWorker class. And here's an example:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.XPath;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync(txtUrl.Text);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var rssDoc = XDocument.Load((string)e.Argument);
var items = new List<ListViewItem>();
foreach (var item in rssDoc.XPathSelectElements("//item"))
{
var listItem = new ListViewItem();
listItem.Text = item.Element("title").Value;
listItem.SubItems.Add(item.Element("link").Value);
items.Add(listItem);
}
e.Result = items.ToArray();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lstView.Items.AddRange((ListViewItem[])e.Result);
}
}
If you're using .NET 3.5 or later you can use the SyndicationFeed type to make parsing the RSS feed easier.
I'm adapting Darin Dimitrov's code example here:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.ServiceModel.Syndication;
using System.Xml.Linq;
using System.Xml.XPath;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync(txtUrl.Text);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var reader = new XmlTextReader((string)e.Argument);
var feed = SyndicationFeed.Load(reader);
var items = new List<ListViewItem>();
foreach (var item in feed.Items)
{
var listItem = new ListViewItem();
listItem.Text = item.Title;
foreach (var link in item.Links)
{
listItem.SubItems.Add(link.Uri.AbsoluteUri);
}
items.Add(listItem);
}
e.Result = items.ToArray();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lstView.Items.AddRange((ListViewItem[])e.Result);
}
}
If you are using .net 4.0 you can use the Task system for an even easier approach, and possibly better performance.
foreach (var item in rssDoc.XPathSelectElements("//item"))
{
Task fetch = new Task(() =>
{
// Go to server and get data....
// Add Data to UI...
});
fetch.Start();
}
The main benefit here is the Task system will decide how and when to run each fetch operation. In theory each operation will run in its own thread, so one or more at a time will be active instead of just one that you would see in a normal loop. The system is nice enough to do some load balancing for you too.