ArrayList in comboBox - c#

I need help with creating an ArrayList that adds words into a ComboBox, which then allows the user to click on the word and then it gets inserted into a RichTextBox. I do have the following code but it does not work. Hope someone could assist me please.
public partial class WordEditorApp : Form
{
//Creating an arraylist for the combobox.
ArrayList al = new ArrayList();
public WordEditorApp()
{
InitializeComponent();
//Initializing the radio buttons.
upperCase.Checked = false;
lowerCase.Checked = false;
//Adding items to the arraylist.
al.Add("Grams");
al.Add("Aristrocrats");
al.Add("Sophisticated");
al.Add("Corruption");
al.Add("Interrupt");
al.Add("Operation");
al.Add("Decision");
al.Add("Bantam");
al.Add("Brochure");
al.Add("Hydraulics");
al.Add("Properties");
//for loop to add items to the arraylist.
for (int i = 0; i < al.Count; i++)
{
comboBox1.Items.Add(al[i].ToString());
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
//Selected word from the combo box is appended into the textbox.
richTextBox1.AppendText(ArrayList.SelectedItem.ToString());
}
catch (Exception) { }
}

A simpler alternative
string[] al = { "Grams", "Aristrocrats", "Sophisticated", "Corruption", "Interrupt",
"Operation", "Decision", "Bantam", "Brochure", "Hydraulics", "Properties" };
comboBox1.Items.AddRange(al);

This is how I would do it:
Start by using current, efficient, type-safe and extensible objects and methods:
List<string> words = new List<string>()
{
"Grams", "Aristrocrats", "Sophisticated",
"Corruption", "Interrupt", "Operation",
"Decision", "Bantam", "Brochure", "Hydraulics", "Properties"
};
comboBox1.Items.AddRange(words.ToArray());
Then I would not append the text but set it as the SelectedText; this means the user can insert it anwhere, thus providing append, insert and replace all in one go:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
richTextBox1.SelectedText = comboBox1.SelectedItem.ToString();
}
Adding a space after each word may also be a friendly idea..
Note that if you only want to load a fixed number of items you can do it like this as well:
comboBox1.Items.AddRange(new[] { "Grams", "Aristrocrats", "Sophisticated",
"Corruption", "Interrupt", "Operation", "Decision",
"Bantam", "Brochure", "Hydraulics", "Properties" });
Here no local list or array is needed and the type is resolved from the values.
But if you declare a List<string> at class level you can expand it with new words the user enters and later store it in a file, creating a growing word list..

I thing this is wrong:
//Selected word from the combo box is appended into the textbox.
richTextBox1.AppendText(ArrayList.SelectedItem.ToString());
^
ArrayList doesnt have a static property called SelectedItem.
Did you mean comboBox1.SelectedItem.ToString(); ?

Try the below code.
richTextBox1.AppendText(comboBox1.Text);
You are trying to append text from ArrayList..

If you insist on ArrayList class (which is deprecated):
// static: you want just one instance for all WordEditorApp instances
private static ArrayList al = new ArrayList() {
"Grams",
"Aristrocrats",
"Sophisticated",
"Corruption",
"Interrupt",
"Operation",
"Decision",
"Bantam",
"Brochure",
"Hydraulics",
"Properties"
};
...
comboBox1.Items.AddRange(al.OfType<String>());
a better design is to change ArrayList to List<String> or String[]:
private static String[] al = new String[] {
"Grams",
"Aristrocrats",
...
"Properties"
};
...
// No need in OfType<String>() here
comboBox1.Items.AddRange(al);

Related

C# CheckedListBox how to manipulate checked data?

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.

Set and get checked boxes in MultiSelectListPreference

I'm defining the MultiSelectListPreference in my axml file like this:
<MultiSelectListPreference
android:title="Title"
android:summary="Sum"
android:key="dutyMarks"
android:entries="#array/array_marks"
android:entryValues="#array/array_marksValues">
</MultiSelectListPreference>
How can check / read the checked boxes in code?
I tried to get the checked values via the PreferenceChange event:
The checked values appear there, but I have no idea how to get them...
This was also my first thought, but e.NewValue doesn't contain a public definition for 'GetEnumerator'.
We can simply cast e.NewValue from object to IEnumerable in our code, for example:
private void PreferenceChange(object sender, Preference.PreferenceChangeEventArgs e)
{
var selections = e.NewValue as IEnumerable;
if (selections != null)
{
foreach (var selection in selections)
{
Console.WriteLine(selection);
}
}
}
since e.NewValue is a HashSet, you should be able to iterate through it
foreach (string x in e.NewValue) {
// do whatever you need to do with each value x here
}
If someone stumbles across this question, here is how i solved it:
Read (the async part is pretty ugly, but I don't know how to add a 'preferenceChangeD' event)
private async void preferenceChange(object sender, Preference.PreferenceChangeEventArgs e)
{
await System.Threading.Tasks.Task.Delay(100);
List<string> sList = new List<string>();
ICollection<string> selectedValues = mslp_dutyMarks.Values;
foreach(string x in selectedValues)
sList.Add(x);
}
Write
mslp_dutyMarks.Values = new List<string> { "A", "B", "C" };

value does not fall within expected range

I'm working on a windows phone project. I have a listbox with the following selectionchanged event handler:
private void judgeType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LoadJudgeCategories(judgeTypeListBox.SelectedItem.ToString());
}
Here is the LoadJudgeCategories method:
void LoadJudgeCategories(string judgeType)
{
string[] categories = judgeCategories[judgeType];
List<LabeledTextBox> itemSource = new List<LabeledTextBox>();
foreach (string cat in categories)
{
itemSource.Add(new LabeledTextBox(cat));
}
CategoryPanel.ItemsSource = itemSource;
}
judgeCategories is of type
Dictionary<string, string[]>
LabeledTextBox is usercontrol with a textblock and a textbox. CategoryPanel is just a listbox.
Whenever the selected item is changed, I want to clear CategoryPanel, and replace it with a new List.
Occasionally, however, when I change the selection, it gives the exception "value does not fall within the expected range".
How do I fix this?
This can happen when you add multiple controls with the same name. Try this code. Broken down with newlines for clarity. I turned it into a linq statement, and also named each of the LabeledTextBox something random.
Note: the only important thing I did was give the LabeledTextBox a name.
Random r = new Random();
void LoadJudgeCategories(string judgeType)
{
CategoryPanel.ItemsSource =
judgeCategories[judgeType]
.Select(cat =>
new LabeledTextBox(cat) { Name = r.Next().ToString() }
).ToList();
}
Just an alternative solution with ObservableCollection - there will be no need to set CategoryPanel.ItemsSource multiple times:
private ObservableCollection<LabeledTextBox> itemSource = new ObservableCollection<LabeledTextBox>();
CategoryPanel.ItemsSource = itemSource; // somewhere in the Constructor
void LoadJudgeCategories(string judgeType)
{
itemSource.Clear();
foreach (string cat in judgeCategories[judgeType])
itemSource.Add(new LabeledTextBox(cat));
}

The BindingList Datasource of a Combobox refreshes correctly but the Combobox displays items in the wrong order

I have a BindingList< KeyValuePair < string, string > > that is bound to a ComboBox control. Based on some conditions, the BindingList will be added a new KeyValuePair. Now, the Newly added item shows up at index 0 of the Combobox, instead of at the end.
While debugging, I found that the BindingList has got the right order. (i.e, the new KeyValuePair is appended)
Also, I check the SelectedValue of the ComboBox in it's SelectedIndexChanged handler and it seems to be not of the ListItem that got selected. Instead, it is that of the supposed ListItem, if the ComboBox had got the right order as in its DataSource, - the BindingList..
The code is a small part of a large project.. Plz let me know if the question is not clear. I can put the relevant parts of the code as per our context.
How could something like this happen? What can I do differently?
I have this class something like this.
public class DropdownEntity
{
//removed all except one members and properties
private string frontEndName
public string FrontEndName
{
get {return this.frontEndName; }
set {this.frontEndName= value; }
}
//One Constructor
public DropdownEntity(string _frontEndName)
{
this.FrontEndName = _frontEndName;
//Removed code which initializes several members...
}
//All methods removed..
public override string ToString()
{
return frontEndName;
}
}
In my windows form, I have a tab control with several tabs. In one of the tabs pages, I have a DataGridView. The user is supposed to edit the cells and click on a Next - button. Then, some processing will be done, and the TabControl will be navigated to the next tab page.
The next tab page has the combobox that has the problem I mentioned. This page also has a back button, which will take back.. the user can modify the gridview cells again.. and click on the next button. This is when the order gets messed up.
I am posting here the Click event handler of the Next Button.. Along with the class, with the rest of the code removed.
public partial class AddUpdateWizard : Form
{
//Removed all members..
BindingList<KeyValuePair<string, string>> DropdownsCollection;
Dictionary<string, DropdownEntity> DropdownsDict;
//Defined in a partial definition of the class..
DataGridView SPInsertGridView = new DataGridView();
ComboBox DropdownsCmbBox = new ComboBox();
Button NextBtn2 = new Button();
Button BackBtn3 = new Button();
//Of course these controls are added to one of the panels
public AddUpdateWizard(MainForm mainForm)
{
InitializeComponent();
DropdownsDict = new Dictionary<string, DropdownEntity>();
}
private void NextBtn2_Click(object sender, EventArgs e)
{
string sqlArgName;
string frontEndName;
string fieldType;
for (int i = 0; i < SPInsertGridView.Rows.Count; i++)
{
sqlArgName = "";
frontEndName = "";
fieldType = "";
sqlArgName = SPInsertGridView.Rows[i].Cells["InsertArgName"].Value.ToString().Trim();
if (SPInsertGridView.Rows[i].Cells["InsertArgFrontEndName"].Value != null)
{
frontEndName = SPInsertGridView.Rows[i].Cells["InsertArgFrontEndName"].Value.ToString().Trim();
}
if (SPInsertGridView.Rows[i].Cells["InsertArgFieldType"].Value != null)
{
fieldType = SPInsertGridView.Rows[i].Cells["InsertArgFieldType"].Value.ToString().Trim();
}
//I could have used an enum here, but this is better.. for many reasons.
if (fieldType == "DROPDOWN")
{
if (!DropdownsDict.ContainsKey(sqlArgName))
DropdownsDict.Add(sqlArgName, new DropdownEntity(frontEndName));
else
DropdownsDict[sqlArgName].FrontEndName = frontEndName;
}
else
{
if (fieldType == "NONE")
nonFieldCount++;
if (DropdownsDict.ContainsKey(sqlArgName))
{
DropdownsDict.Remove(sqlArgName);
}
}
}
//DropdownsCollection is a BindingList<KeyValuePair<string, string>>.
//key in the BindingList KeyValuePair will be that of the dictionary.
//The value will be from the ToString() function of the object in the Dictionary.
DropdownsCollection = new BindingList<KeyValuePair<string,string>>(DropdownsDict.Select(kvp => new KeyValuePair<string, string>(kvp.Key, kvp.Value.ToString())).ToList());
DropdownsCmbBox.DataSource = DropdownsCollection;
DropdownsCmbBox.DisplayMember = "Value";
DropdownsCmbBox.ValueMember = "Key";
//Go to the next tab
hiddenVirtualTabs1.SelectedIndex++;
}
private void BackBtn3_Click(object sender, EventArgs e)
{
hiddenVirtualTabs1.SelectedIndex--;
}
//On Selected Index Changed of the mentioned Combobox..
private void DropdownsCmbBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropdownsCmbBox.SelectedValue != null)
{
if (DropdownsDict.ContainsKey((DropdownsCmbBox.SelectedValue.ToString())))
{
var dropdownEntity = DropdownsDict[DropdownsCmbBox.SelectedValue.ToString()];
DropdownEntityGB.Text = "Populate Dropdowns - " + dropdownEntity.ToString();
//Rest of the code here..
//I see that the Datasource of this ComboBox has got the items in the right order.
// The Combobox's SelectedValue is not that of the selected item. Very Strange behavior!!
}
}
}
}
The very first time the user clicks the Next Button, it's fine. But if he clicks the Back Button again and changes the Data Grid View cells.. The order will be gone.
I know, it can be frustrating to look at. It's a huge thing to ask for help. Any help would be greatly appreciated!
Please let me know if you need elaboration at any part.
Thanks a lot :)
I think you have two problems here.
First, if you want to retain the order of the items you should use an OrderedDictionary instead of a regular one. A normal collection will not retain the order of the items when you use Remove method. You can see more info about this related to List here.
You could use such dictionary like this:
DropDownDict = new OrderedDictionary();
// Add method will work as expected (as you have it now)
// Below you have to cast it before using Select
DropDownCollection = new BindingList<KeyValuePair<string, string>>(DropDownDict.Cast<DictionaryEntry>().Select(kvp => new KeyValuePair<string, string>(kvp.Key.ToString(), kvp.Value.ToString())).ToList());
The second problem could be that you change the display name (FrontEndName) of already existing items, but the key is preserved. When you add a new item, try to remove the old one that you're not using anymore and add a new item.
The Sorted Property of the Combobox is set to True! I didn't check that until now. I messed up. Terribly sorry for wasting your time Adrian. Thanks a lot for putting up with my mess here.. :)

Dynamically adding LinkLabels to a TableLayoutPanel

I've been having a problem with the following code:
namespace Viewer
{
public partial class Form1 : Form
{
int count = 0;
LinkLabel[] linkLabel = new LinkLabel[200];
string filename;
string extension;
string filepath;
private void btnLoad_Click(object sender, EventArgs e)
{
// Creates a Directory for the Movies Folder
DirectoryInfo myDirectory = new DirectoryInfo(#"C:\Users\User\Movies");
// Creates a list of "File info" objects
List<FileInfo> ls = new List<FileInfo>();
// Adds filetypes to the list
ls.AddRange(myDirectory.GetFiles("*.mp4"));
ls.AddRange(myDirectory.GetFiles("*.avi"));
// Orders the list by Name
List<FileInfo> orderedList = ls.OrderBy(x => x.Name).ToList();
// Loop through file list to act on each item
foreach (FileInfo filFile in orderedList)
{
// Creates a new link label
linkLabel[count] = new LinkLabel();
// Alters name info for display and file calling
filepath = filFile.FullName;
extension = filFile.Extension;
filename = filFile.Name.Remove(filFile.Name.Length - extension.Length);
// Write to the textbox for functional display
textBox1.AppendText(filename + "\r\n");
// Alters link label settings
linkLabel[count].Text = filename;
linkLabel[count].Links.Add(0, linkLabel[count].Text.ToString().Length, filepath);
linkLabel[count].LinkClicked += new LinkLabelLinkClickedEventHandler(LinkedLabelClicked);
// Adds link label to table display
tblDisplay.Controls.Add(linkLabel[count]);
// Indexes count up for arrays
count = count + 1;
}
}
private void LinkedLabelClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(filepath);
}
}
}
My goal is to generate a table of links to all of the media files that I add at launch, and have the links open the files in their respective players.
As of right now, it generates all of the links properly, but whenever I click on any of them, it launches the last item in the list.
For example, if the list contains "300", "Gladiator", and "Top Gun", no matter which link I click, it opens "Top Gun".
I assume that this has to do with it calling the variable "filepath" in the click event, which is left in it's final state. However, I'm not exactly clear on how to create a static link value or action on each individual link, as all of the answers I've researched are in regards to single linklabel situations, not dynamic set-ups.
Any help/advice would be appreciated!
Try as below:
In foreach loop add one line more like:
linkLabel[count].Tag = filepath;
then in click event get this path as blow,
private void LinkedLabelClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
string filepath = ((LinkLabel)sender).Tag.tostring();
System.Diagnostics.Process.Start(filepath);
}

Categories

Resources