I'm trying to fill a listview with a database, with each row displaying an image retrieved from a path. It works and an image is displayed in the row, but the problem is that the same image shows up for every list item. So it uses the image from the first database entry for all of the entries.
Here is the code retrieving and displaying the images:
DataTable tab = myConn.GetSchema("Tables");
foreach (DataRow row in tab.Rows) {
Console.WriteLine("{0}", row["TABLE_NAME"].ToString());
}
string mySelectQuery = "Select * from staff";
OdbcCommand command = new OdbcCommand(mySelectQuery, myConn);
OdbcDataReader reader = command.ExecuteReader();
ImageList imgList = new ImageList();
while (reader.Read()) {
ListViewItem item = new ListViewItem(reader.GetString(0), 0);
item.SubItems.Add(reader.GetString(1));
item.SubItems.Add(reader.GetString(2));
// gets image from path in db
imgList.Images.Add(Image.FromFile(reader.GetString(3)));
listView1.SmallImageList = imgList;
item.SubItems.Add(reader.GetString(4));
item.ImageIndex = 0;
listView1.Items.AddRange(new ListViewItem[] { item });
}
You're sharing the same imageList object among all of them. You create it before entering the loop, and then on each iteration, you add another image to the end, but you always tell each new listview item to use the first image in the list. Since it's the same list object every time, that's the same first image every time.
You could just create a new image list for each item:
while (reader.Read()) {
// Create a new one each time.
ImageList imgList = new ImageList();
ListViewItem item = new ListViewItem(reader.GetString(0), 0);
Related
I'm dynamically updating a ListView like that:
ListViewItem item = new ListViewItem();
item.Text = "Text1";
item.SubItems.Add("Text2");
item.SubItems.Add("Text3");
item.SubItems.Add("Text4");
item.Tag = i;
listView.Items.Add(item);
now I want that instead of Text4 will be a lil icon I will get dynamically from a url. I read a lot of threads and tried many things - but I can't get this to work..
You need to implement ImageList in your function.
Code :
// get picture resource
WebClient _web = new WebClient();
byte[] _data = _wb.DownloadData("http://www.myzony.com/usr/uploads/2017/03/3197402477.png");
MemoryStream _ms = new MemoryStream(_data);
// Loaded to imagelist
ImageList list = new ImageList();
list.Images.Add("pic1",Image.FromStream(_ms));
// bind listview
listView1.SmallImageList = list;
ListViewItem _item1 = new ListViewItem();
_item1.Text = "Test";
_item1.SubItems.Add("Test2");
_item1.SubItems.Add("pic1");
_item1.ImageKey = "pic1";
listView1.Items.Add(_item1);
Effect Image:
I bound my datatable to datagridview, every column shows the correct data. But on my Image Column in datagridview does not show the image, instead it shows System.Drawing.Bitmap string.
My codes are;
// I create the data column for my Image and add this to the datatable
DataColumn dc = new DataColumn("QR Code", typeof(Image));
dc.AllowDBNull = true;
dTable.Columns.Add(dc);
// I loop through all rows in datatable get the byte array of the image, and convert it to an Image
// And then add this image to the newly created column.
foreach (DataRow dr in dTable.Rows)
{
Image qrCode;
byte[] qrCodeBytes = (byte[])dr["StockQRCode"];
using(MemoryStream stream = new MemoryStream(qrCodeBytes))
{
qrCode = Image.FromStream(stream);
dr[dc] = qrCode;
}
}
// Bind my datatable to datagridview
List_ListContainer.DataSource = dTable;
What am I missing?
I have created a image grid view using ListView and ImageList.. image names come from database and images are stored in categories folder. I adding images imgList.Images.Add("", Image.FromFile(#"./categories/" + dr["image"]));
but when program runs 1st list view item not set to the correct image, 1stlistviewitem with second image, i think there is a indexing error. is something wrong with my code or any way to solve this?
private void LoadCategories() {
DataTable categories;
con = new Dbfunctions();
con.MysqlQuery("SELECT * FROM categories WHERE online = 1");
categories = con.QueryEx();
//ImageList
ImageList imgList = new ImageList();
//CLEAR listview_Category items
listView_Category.Items.Clear();
//set listview category items as Large icons
listView_Category.View = View.LargeIcon;
//ADD image list into Listview
listView_Category.LargeImageList = imgList;
int i = 0;
//ADD image into imagelist and Listview
foreach(DataRow dr in categories.Rows){
imgList.Images.Add("", Image.FromFile(#"./categories/" + dr["image"]));
ListViewItem category = new ListViewItem();
//bind listview item vwith image list item
category.ImageIndex = i;
//set Category name
category.Text = dr["name"].ToString();
//set font list items styles
category.Font = new System.Drawing.Font("Courier New", 15, System.Drawing.FontStyle.Regular);
category.ForeColor = System.Drawing.Color.FromArgb(252, 119, 123);
//ADD category items into Listview
listView_Category.Items.Add(category);
imgList.ImageSize = new Size(140, 140);
imgList.ColorDepth = ColorDepth.Depth32Bit;
i++;
}
}
Please provide shapes of DB rows. Maybe you have a missmatch in DB so you call not proper index.
I have problem with creating listview. I am new in C# and wpf too.
I have tried different methods of filling ListView items and I can not solve it, because the input array is NxN dimensions. I found instructions on Bindig but I can not apply them because I can not create an object of that type, because the input array is dynamic.
I can fill header columns but no rows and columns with values. This code works but all values are together in one column.
public void PrintListView(ResultsTable results)
{
System.Windows.Controls.GridView gv = new System.Windows.Controls.GridView();
gv.AllowsColumnReorder = true;
int j=0;
foreach (DataColumn dc in results.Columns)
{
GridViewColumn gvCol = new GridViewColumn();
gvCol.Header = results.Columns[j].ColumnName;
gvCol.Width = 200;
gv.Columns.Add(gvCol);
j++;
}
lbVysledky.View = gv;
foreach (DataRow dr in results.Rows)
{
string[] array1 = new string[1000];
// List<string> zoznam = new List<string>();
// ObservableCollection<string> kolekcia = new ObservableCollection<string>();
int i = 0;
foreach (DataColumn dc in results.Columns)
{
array1[i] = dr[dc].ToString();
// zoznam.Add (dr[dc].ToString());
// kolekcia.Add(dr[dc].ToString());
i++;
}
this.lbVysledky.Items.Add(new ListViewItem { Content = pole[0] + pole[1]});
}
}
Can someone help me? Thanks
It looks like you're trying to populate the ListView by adding rows and columns one at a time. This is not the approach to use when populating a ListView. Instead, you add the ItemsSource (in this case, your results object) and tell the ListView what the DisplayMemberBinding is for each column, and it will display the proper values in each column for each row.
It probably just means modifying your loop where you add columns to the ListView to something like this:
foreach (DataColumn dc in results.Columns)
{
GridViewColumn gvCol = new GridViewColumn();
gvCol.DisplayMemberBinding = new Binding(dc.ColumnName);
gvCol.Header = results.Columns[j].ColumnName;
gvCol.Width = 200;
gv.Columns.Add(gvCol);
j++;
}
lbVysledky.View = gv;
Then just set the ItemsSource of the ListView to your results object like this:
lbVysledky.ItemsSource = results;
Also, as a side note, you don's appear to be using the foreach construct correctly. you're enumerating over each column, but you're keeping your own counter and accessing the column like this:
gvCol.Header = results.Columns[j].ColumnName;
In a foreach loop, you're already enumerating the columns with the dc variable, so you can access the column like this:
gvCol.Header = dc.ColumnName;
and you don't need to manually count the columns (with j).
I have 2 list boxes. i want to fill id and value to listbox1 from database. Then I want to add selected items to listbox2 and remove items from listbox1.
List<Plan> lstPlan = new List<Plan>();
SqlDataReader rd = null;
try
{
STS_STORE_PROC_SCHEME.GetPlanParameter objInsert = new STS_STORE_PROC_SCHEME.GetPlanParameter();
objInsert.GetPlan_fun(ref rd, ref ds, SqlReturnType.DATASET_sts);
//while (rd.Read())
//{
// lstPlan.Add(new Plan(Convert.ToInt32(rd[0].ToString()), rd[1].ToString()));
//}
//for (int i = 0; i < lstPlan.Count; i++)
//{
// listBox1.Items.Add(lstPlan[i].ToString());
// //from.Items.Remove(items[i]);
//}
listBox1.DataSource = ds.Tables[0].DefaultView;
listBox1.DisplayMember = "Planname";
listBox1.ValueMember = "nvcharPlanName";
}
catch (Exception ex)
{
}
Its giving error
Items collection cannot be modified when the DataSource property is
set.
I guess you ll need to modify the data that backs the listbox (ds.Tables[0]) and rebind it to the listbox like you do at the line:
listBox1.DataSource = ds.Tables[0].DefaultView;
Similarly, for adding and removing from one listbox to another, simply, you can
define two lists
make your manipulations on these lists (add items from one another,
remove..etc)
set these lists as the DataSource s of the individual listboxes
EDIT:
Code snippet..
Dictionary<int, Plan> dicPlan1 = new Dictionary<int, Plan>();
dicPlan1.Add(1, new Plan());
dicPlan1.Add(2, new Plan());
dicPlan1.Add(3, new Plan());
dicPlan1.Add(4, new Plan());
listbox1.DataSource = new List<Plan>(dicPlan1.Values); //this will get you only the plans
Dictionary<int, Plan> dicPlan2 = new Dictionary<int, Plan>();
dicPlan2.Add(1, new Plan());
dicPlan2.Add(2, new Plan());
dicPlan2.Add(3, new Plan());
dicPlan2.Add(4, new Plan());
listbox2.DataSource = new List<Plan>(dicPlan2.Values); //this will get you only the plans
Then if you want to add from 1st collection to the 2nd collection:
dicPlan2.Add(dicPlan1[1]);
Remove from a collection using the index
dicPlan1.RemoveAt(0); // removes the first item!! (not this => dicPlan2.Add(1, new Plan());)
Simple as that.. donT forget. In order to see the updates in your listboxes, you need to set the datasource again after changing the lists.
listbox1.DataSource = new List<Plan>(dicPlan1.Values);
listbox2.DataSource = new List<Plan>(dicPlan2.Values);
Hope it helps.