C# CheckedListBox how to manipulate checked data? - c#

Hey guys new to C# and I am trying to setup a GUI, all I want the GUI to do is have a simple file explorer with a CheckedListBox to represent selected files.
I can get the CheckedListBox to show up and click on files but I'm not sure how to continue from here, most tutorials stop here, or go too advanced with tree view and other things that seem unnecessary for what I am trying to do.
Here is my code:
Any help is appreciated and if you guys could point me in the right direction that would be awesome.
EDIT:
To rephrase my question:
I want the user to select files through the CheckedListBox (user input stops here), and for those selected files to be put in a list that my code can manipulate.
Not sure how to accomplish this after my first foreach loop (which adds all files in the selected directory to the CheckedListBox for user selection).
The second foreach loop is an attempt at this, manipulating the files so that they output their filenames after being selected. However no Messagebox shows up and I assume that their is a disconnect between the user selecting files and the codes attempt at manipulating said files.
Second Edit:
I think I figured it out I made a second button and from here it looks like I can manipulate the chosen files however I want.
Currently the code is working the way I would expect it to work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace SelectFiles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
checkedListBox1.CheckOnClick = true;
}
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
MessageBox.Show(fbd.SelectedPath);
checkedListBox1.Items.Clear();
string[] files = Directory.GetFiles(fbd.SelectedPath);
foreach (string file in files)
{
checkedListBox1.Items.Add(file);
}
}
private void button2_Click_1(object sender, EventArgs e)
{
List<string> list_all_excelfiles = new List<string>();
foreach (string item in checkedListBox1.CheckedItems)
{
list_all_excelfiles.Add(item);
MessageBox.Show(Path.GetFileName(item));
}
}
}
}

First i advice you to assign Value member and Display member for each item.
Display Member will be visible to user
Value Member will we use in code
To do this first create simple custom class
public class Int_String
{
public int _int { get; set; }
public string _string { get; set; }
}
Be careful because get; set; part is important to be there since if not code will not work
Now what you need to do is create list of items with custom class like this
class YourForm : Form
{
List<Int_String> myList = new List<Int_String>(); //Create list of our custom class
public YourForm()
{
PopulateMyList();
}
private void PopulateMyList()
{
//Here read from database or get data somehow and populate our list like this
//I will populate it manually but you do it in foreach loop
myList.Add(new Int_String { _int = 0, _string = "First Item" });
myList.Add(new Int_String { _int = 1, _string = "Second Item" });
myList.Add(new Int_String { _int = 2, _string = "Third Item" });
}
}
After that you need to assign this list to your checkedListBox which you will do like this:
public YourForm()
{
PopulateMyList();
checkedListBox1.DataSource = myList;
checkedListBox1.DisplayMember = "_string";
checkedListBox1.ValueMember = "_int";
}
And now when you can manipulate with checked items like this:
for(int i = 0; i < checkedListBox1.Items.Count; i++)
{
if(checkedListBox1.Items[i].CheckedState == CheckState.Checked)
{
int itemValueMember = (checkedListBox1.Items[i] as Int_String)._int;
int itemDisplayMember = (checkedListBox1.Items[i] as Int_String)._string;
//Use these two vars for whatever you need
}
}
TWO IMPORTANT TIPS:
I am not sure for this one since i am writing all this from head but i think that visual studio will not show you that there is DisplayMember or ValueMember for checkedBox component BUT also it will not show error. Reason is that they have hidden in intentionally for idk what reason but it will work.
You are able to assign Display and Value member to a lot of components in winforms BUT for some reason checkedListBox is specific. It is specific because you MUST first assign DataSource to it and then tell it checkedListBox.DisplayMember = "_string" ...... For new guy you will ask why it is important. Simple answer is create custom list for test and add 10k items inside it and then first declare datasource and after it Display and Value member. Test how long form will need to load (get out of freeze state). After that do everything same but first declare Display and Value member and then assign datasource and test again. I am telling this from head without testing but before when i needed about 5k rows with 1st solution it took me about 30 sec and second < 1 sec. If you want to know more about it google it but for now this is pretty much info for you.

Related

How to save a listview of data to a .txt in C# so it can be accessed the next time the form is open?

How can I save the the data in a listview?
For example if the user has put something into the listview and then closes the application, all that information is then lost. Is there any way of saving the information as soon as they put something into the listView?
This is the code I use to input the information from a textbox to the listView1:
string[] items = { titletxt.Text, statustxt.Text };
ListViewItem lvi = new ListViewItem(items);
listView1.Items.Add(lvi);
UPDATE (29/12/2012)
Thanks for all the help! But I can't seem to get it working. I have created a really simple form to try and get it working. It has 3 textboxes (NameTxt, AgeTxt, HairColourTxt), a button, and the listview(ListOfPeople).
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace listview
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string[] items = { NameTxt.Text, AgeTxt.Text, HairColourTxt.Text };
ListViewItem lvi = new ListViewItem(items);
ListOfPeople.Items.Add(lvi);
}
}
}
I have tried to add the code posted by #user574632 & #Joe & #DmitryKvochkin and I have changed bits but still cant get it to work. I'm not sure what I'm doing wrong? I have tried to add this:
private void saveListOfPeopleItems(string path, ListView lv)
{
var delimeteredListviewData = new List<string>();
foreach (ListViewItem lvi in lv.Items)
{
string delimeteredItems = string.Empty;
foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems)
{
delimeteredItems += lvsi.Text + "#";
}
delimeteredListviewData.Add(delimeteredItems);
}
System.IO.File.WriteAllLines(path, delimeteredListviewData.ToArray());
}
private void loadListOfPeopleItems(string path, ListView lv)
{
foreach (string line in System.IO.File.ReadAllLines(path))
{
lv.Items.Add(new ListViewItem(line.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries)));
}
}
You need to create the save logic, there's no automatic method.
The easiest way is to use Serialization (look for ISerializable) to save to a file of your choice (name it whatever you like): You can save entire objects this way. Here is a simple tutorial on serialization.
The other method is to parse the listview content into strings (keep only what you need), and you save the strings to a text file (TextReader and TextWriter).
If you want to save application settings (and not user data), have a look at this link, or this one which might be easier to read.
Finally, if you need to interact with the data you save regularly, or if you have a lot of data to store, use a database (SQL, mySQL, etc). The latter method is the longest one to implement.
if you want to save to a text file, you could use the following:
private void saveListViewItems(string path, ListView lv)
{
var delimeteredListviewData = new List<string>();
foreach (ListViewItem lvi in lv.Items)
{
string delimeteredItems = string.Empty;
foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems)
{
delimeteredItems += lvsi.Text + "#";
}
delimeteredListviewData.Add(delimeteredItems);
}
System.IO.File.WriteAllLines(path, delimeteredListviewData.ToArray());
}
private void loadListViewItems(string path, ListView lv)
{
foreach (string line in System.IO.File.ReadAllLines(path))
{
lv.Items.Add(new ListViewItem(line.Split(new char[]{'#'}, StringSplitOptions.RemoveEmptyEntries)));
}
}
You can use integrated visual studio settings and than bind it to your listview, even in designer. After you changed your listview you can save them
I would say the answer is : use .txt files
Also you can create an SQL database, and save it there...

Keeping track of 40+ control values

I am in need of some guidance for the following design.
I have a tab control that contains various group boxes. Within the group box, there are specific controls that relates to that group box. For example:
Now whenever a change is made to any control in the group box, the value for the control needs to be tracked because at the end of the application run cycle, the control data will need to be saved to a file that contains that value. An example file is:
HOT_STANDBY_FEATURE_ENABLE [val from control here]
HEART_BEAT_DIGITAL_OUTPUT [val from control here]
....
A design that I have in mind has another that has just properties that the group box form sets whenever a ValueChanged event occurs on a control.
Example code:
class ConfigurationValues
{
public int HotStandbyValue { get; set; }
public int HeartBeatDigitalOutputValue { get; set; }
//...add all other controls here
}
The downside that I see to this is that there are 40 controls on that tab page, so I'd have to manually type each property. When the file needs to be generated at the end of the application run cycle, I have a method that gets the value of the control need.
Example:
private void GenerateFile()
{
string[] file =
"HOT_STANDBY_FEATURE_ENABLE " + ConfigurationTabSettings.HotStandbyValue;
}
Another design consideration I need to make is that whenever a user clicks "Open Configuration File", the values from the file from disk need to be loaded into the properties so the form can take that data on startup and populate the controls within the group boxes with their respective values.
Any suggestions on this design would be greatly appreciated. I know this is not the most efficent way to do this and am not the most experienced programmer, so any Google keywords I can search for would be great also.
You could xml serialise and xml deserialise your ConfigurationValues class rather than writing manual "generate file" and "read file" methods
http://support.microsoft.com/kb/815813
You'll need to bind the controls Text or Value properties to the properties in your ConfigurationValues class e.g.
ConfigurationValues cv = Repository.ReadConfigValues();
numPulseFilterDelay.DataBindings.Add("Value", cv, "PulseFilterDelay");
// Add the rest of your control bindings here
on the btnSave_Click() of your Form, end the current edit on the form and save the config values
void btnSave_Click(object sender, EventArgs e)
{
BindingContext[cv].EndCurrentEdit(); // Commits all values to the underlying data source
Repository.SaveConfigValues(cv);
}
In your repository class you'll need methods to Load() and Save() the data. You can put XmlSerialization code in here, or write your own format (depending on your requirements)
public class Repository
{
public static ConfigurationValues LoadConfigValues()
{
var cv = new ConfigurationValues();
string[] lines = File.ReadAllLines("values.cfg");
foreach (string cfg in lines)
{
string[] nameValue = cfg.Split(new char[] { ' ' } ); // To get label/value
if (nameValue[0] == "HOT_STANDBY_FEATURE_ENABLE")
cv.HotStandbyFeatureEnable = nameValue[1];
else if (nameValue[0] == "SOME_OTHER_PROPERTY")
cv.SomeOtherProperty = nameValue[2];
// Continue for all properties
}
return cv;
}
public static void SaveConfigValues(ConfigurationValues cv)
{
var builder = new StringBuilder();
builder.AppendFormat("HOST_STANDBY_FEATURE_ENABLE {0}\r\n", cv.HostStandbyFeatureEnable);
// Add the rest of your properties
File.WriteAllText("values.cfg", builder.ToString());
}
}

How to hold a table of data for user edition (before saving in the the database)?

I've been using this programming style, that I've seen in an example and just started using it, because it does the job... I would like to know other programmers' opinion about it...
So the situation is when you have a GridView, or a control based on it like the RadGrid, and you want to keep track of a data table while you are adding, editing, reordering and deleting rows.
Using the session to hold the data table (or list of data) may not be the best solution, because the user may open two identical web pages… Using the ViewState to hold the data may be and option... I have been using an approach like the following:
public partial class DefaultPage : System.Web.UI.Page
{
protected DataLine DefaultDataLine()
{
DataLine dl = new DataLine();
dl = new DataLine();
dl.Number = 0;
dl.Title = "";
dl.Text = "";
return dl;
}
protected class DataLine
{
public int Number { get; set; }
public string Title { get; set; }
public string Text { get; set; }
}
protected static List<DataLine> tempLines;
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
tempLines = RadGridBindStartUpData();
}
}
protected void RadGrid1_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = tempLines;
}
protected void RadGrid1_InsertCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
GridEditableItem editedItem = e.Item as GridEditableItem;
List<DataLine> table = tempLines;
DataLine newRow = new DataLine ();
RadTextBox rtb;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxTitle");
newRow.Title = rtb.Text;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxDescription");
newRow.Description = rtb.Text;
RadNumericTextBox number = (RadNumericTextBox)editedItem.FindControl("RadNumericTextBoxNumber");
newRow.Number = number.Value.HasValue ? Convert.ToInt32(number.Value.Value) : 0;
table.Add(newRow);
}
// ...
So using a static List variable, of a custom object (class), declared in the code-behind of the Aspx page, and updating it whenever the data is edited.
What are your thoughts about this approach? Is it okay? How do you hold your table-format data for edition (prior to saving it in the database)?
Not exactly sure what you're going for, but using a static variable is probably not what you want to do. Static properties are shared across all user/threads, so all concurrent users would be editing the same data.
If you are just looking to persist a small data set across post-backs to the same page, use the ViewState instead. Just be mindful of potential performance issues if you plan on cramming lots of data into it.
It depends on what you're wanting to achieve
Viewstate will keep the data on that page - it won't be available on any other pages (or tabs, or windows)
Session will keep the data on the server, this means it will be available for any page the user is looking at (on your site) and it will keep it until the session times out.
Theres a lot of advtanges/disadvantages to either method, therefore you need to research your situation, here is a start.
You mentioned storing in the session, and how this could cause issues if the user opens up multiple copies of the page, etc...
We had a similar issue so I made a property in code behind on the page and on first page load (if not postback blah blah) I generate a new guid. Then I use the guid value as my session key and I know it'll be unique per page.
You could make a spify property like this...
Public ReadOnly Property SessionDataKey() As String
Get
If ViewState("SessionDataKey") Is Nothing Then
ViewState("SessionDataKey") = Guid.NewGuid()
End If
Return ViewState("SessionDataKey").ToString()
End Get
End Property
But in short, I just use the session.
Thank you very much for your replies! With your help, and some research, I see that both approaches, storing in session or using the static variable are indeed wrong, at least for the purpose I was using them... All your answers were helpful, and although I can only mark one as correct, I would like to leave my appreciation.
Well, for anyone stumbling across the same problem, here’s what I’ve implemented in my pages:
public partial class ScriptAdd : System.Web.UI.Page
{
private List<MyItem> tempMyItems
{
get
{
//if (ViewState["tempMyItemsList"] == null)
// ViewState["tempMyItemsList"] = new List<MyItem>();
return (List<MyItem>)ViewState["tempMyItemsList"];
}
set
{
ViewState.Add("tempMyItemsList", value);
}
}
protected void Page_Load(object sender, EventArgs e)
{
// ...
}
}
And then use it whenever I want to add / insert / update lines to my temporary list:
List<MyItem> table = tempMyItems;
table.RemoveAt(idx);
MyItem newRow = new MyItem ();
// ...
table.Insert(idx, newRow);
Finally, if intended, I store all the items in the database.

How to get the devexpress lookupedit display text from the corresponding edit value

Hai all,
I want to get lookupedit display text when am giving correspond edit value.
example:
if am giving
LookupEdit1.Editvalue="3";
then it should show display text of Editvalue="3"
please help
//code
cmbChemical.Properties.DataSource = _lab.selectChemicals();
cmbChemical.Properties.DisplayMember = "labitem_Name";
cmbChemical.Properties.ValueMember = "labItem_ID";
cmbChemical.Properties.BestFitMode = BestFitMode.BestFit;
cmbChemical.Properties.SearchMode = SearchMode.AutoComplete;
cmbChemical.Properties.Columns.Add(new LookUpColumnInfo("labitem_Name", 100, "Chemicals"));
cmbChemical.Properties.AutoSearchColumnIndex = 1;
You can't, at least not in the way you're trying. The LookUpEdit, as the name implies, looks up its values in a DataSource, eg. a collection of objects. Therefore, to display the value 3 you need to have a list of objects that contains this value and set it as a DataSource for the control.
List<string> values = new List<string>();
values.Add("3");
lookUpEdit.Properties.DataSource = values;
lookUpEdit.EditValue = "3";
Maybe if you specify what are you trying to do, we can help you achieve that.
I think you don't have to specify display member or value member to get your needed behaviour. Following code give me a form with the lookupedit correctly showing "4", and i can choose other values from the list too.
using System.Collections.Generic;
using System.Windows.Forms;
using DevExpress.XtraEditors;
public class Form1 : Form
{
public Form1()
{
var lookUpEdit1 = new LookUpEdit();
Controls.Add(lookUpEdit1);
var source = new List<string>();
for (var i = 0; i < 10;i++ )
source.Add(i.ToString());
lookUpEdit1.Properties.DataSource = source;
lookUpEdit1.EditValue = "4";
}
}
Maybe you get wrong results because you set display member and value member of the control.
This code worked for me.
private void lookUpEdit1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
MessageBox.Show((e.OriginalSource as SLTextBox).Text);
}
}

C# in Visual Studio: How to display a list in a DataGridView? Getting weird stuff

Been a while and I've volunteered to teach myself Windows programming at my company. Started writing vbs scripts and suddenly realized how incredibly useful this programming thing is ;-)
Anyway, I'm a total newbie at C# AND Visual Studio, I kind of get how it works, you drag and drop interface pieces in the design side then wire them together in the back/program side.
I'm trying to write a program that will (ultimately) read in a (very specific kind of) csv file and give the user a friendlier way to edit and sort through it than Excel. Should be simple stuff, and I'm excited about it.
I started this morning and, with the help of the internet, got as far as reading in and parsing the CSV (which is actually a TSV, since they use tabs not commas but hey).
I've been trying to figure out the best way to display the information, and, for now at least, I'm using a DataGridView. But the data isn't displaying. Instead, I'm seeing a long grid of values with column headers of Length, LongLength, Rank, SyncRoot, IsReadOnly, IsFixedSize, and IsSynchronized.
I don't know what any of these mean or where they come from, and unfortunately I don't know how change them either. Maybe somebody can help?
Here is my code:
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 System.IO;
namespace readInCSV
{
public partial class readInCSV : Form
{
public readInCSV()
{
InitializeComponent();
}
public List<string[]> parseCSV(string path)
{
List<string[]> parsedData = new List<string[]>();
try
{
using (StreamReader readfile = new StreamReader(path))
{
string line;
string[] row;
while ((line = readfile.ReadLine()) != null)
{
row = line.Split('\t');
parsedData.Add(row);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return parsedData;
}
//PRIVATE METHODS FROM HERE ON DOWN
private void btnLoadIn_Click(object sender, EventArgs e)
{
int size = -1;
DialogResult csvResult = openCSVDialog.ShowDialog();
if (csvResult == DialogResult.OK)
{
string file = openCSVDialog.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
}
catch (IOException)
{
}
}
dgView.Dock = DockStyle.Top;
dgView.EditMode = DataGridViewEditMode.EditOnEnter;
dgView.AutoGenerateColumns = true;
dgView.DataSource = parseCSV(openCSVDialog.FileName);
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void openCSVDialog_FileOk(object sender, CancelEventArgs e)
{
}
}
}
Thanks in advance!
What's happening here is that the DataGridView is trying to display all the information for each of the string arrays in your parsedData List.
When you set a DataGridView's DataSource as a List of objects, it attempts to interpret each of the objects as a row to display. parsedData is a List of string array objects, so the grid is showing you all the displayable properties for an array object.
What we can do is parse each TSV row into a custom class (call it TsvRow) which has all the relevant data exposed. The TsvRow objects are then placed in a List and passed to the DataGridView. An example of this approach is explained in this article.
For example:
public class TsvRow
{
// Properties to hold column data
public string Column1 { get; set; }
public string Column2 { get; set; }
}
...
public List<TsvRow> parseCSV(string path)
{
List<TsvRow> parsedData = new List<TsvRow>();
try
{
using (StreamReader readfile = new StreamReader(path))
{
string line;
string[] row;
while ((line = readfile.ReadLine()) != null)
{
row = line.Split('\t');
// Here we assume we know the order of the columns in the TSV
// And we populate the object
TsvRow tsvRow = new TsvRow();
tsvRow.Column1 = row[0];
tsvRow.Column2 = row[1];
parsedData.Add(myObject);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return parsedData;
}
Since all your column data is exposed as properties (i.e. "Column1" and "Column2"), they should be reflected in the DataGridView automatically.
Hope that helps! Please let me know if this needs clarification.
The DataGridView tries to display the Properties of your string-Array. You should set AutoGenerateColumns = false and create the columns by yourself.
Would the first line of the CSV/TSV contain the column names? Is so, you shouldn't pass them as DataSource.
dgView.AutoGenerateColumns = false;
foreach(string name in columnNames)
{
dgView.Columns.Add(name, name);
}

Categories

Resources