I am binding my dropdownlist with Enum I have following enum and code for bind dropdownlist.
public enum DignosisOrderType
{
All = 0,
General = 1,
Uveitis = 2,
Coag =3,
PreOp=4,
Tests=5,
RP =6
}
public static void BindDropDownByEnum(DropDownList dropDownList, Type enumDataSource, )
{
Hashtable htDataSource = new Hashtable();
string[] names = Enum.GetNames(enumDataSource);
Array values = Enum.GetValues(enumDataSource);
for (int i = 0; i < names.Length; i++)
htDataSource.Add(names[i], values.GetValue(i));
BindDropDown(dropDownList, htDataSource, "key", "value");
}
public static void BindDropDown(DropDownList dropDownList, object dataSource, string dataTextField, string dataValueField)
{
dropDownList.DataSource = dataSource;
dropDownList.DataTextField = dataTextField;
dropDownList.DataValueField = dataValueField;
dropDownList.DataBind();
}
when the Dropdownlist is bind the data is not comming in sorting order,I want dropdownlist is bind in order of Enum is created.
If you want the items in the order you're adding them, you don't want a hashtable or a SortedList. (A sorted list will be fine while you actually want them in the key sort order anyway, but if you later decide you need to tweak the order, it will cause problems.) In particular, you're not trying to use the ability to look up a value by key, so you don't need an IDictionary<,> at all as far as I can see.
You just want a List<T> for a type containing the key and value. You could do that with an anonymous type, for instance:
var keyValuePairs = Enum.GetValues(enumDataSource)
.Select(x => new { key = x.ToString(), value = x })
.ToList();
BindDropDown(dropDownList, keyValuePairs, "key", "value");
A HashTable isn't the tool for the job then. Try a SortedList.
Remember, A HashTable supports very fast searching, however it does not keep any ordering
There is actually a specialized collection called OrderedDictionary that gives you both abilities: sorting and keyed access.
One thing you could do is iterate through the HT in the BindDropDown method adding one ListItem at a time, so they would be ordered by index.
Just use SortedList or replace HashTable with SortedList
Related
At the top of the form
Dictionary<string, string> FileList = new Dictionary<string, string>();
In the constructor
public Form1()
{
InitializeComponent();
if (System.IO.File.Exists(Path.Combine(path, "test.txt")))
{
string g = System.IO.File.ReadAllText(Path.Combine(path, "test.txt"));
FileList = JsonConvert.DeserializeObject<Dictionary<string, string>>(g);
listBox1.DataSource = FileList.ToList();
}
instead making :
listBox1.DataSource = FileList.ToList();
and then in the listBox i will see for example "hello", "d:\test\test1.txt"
I want that in the listBox there will be only : "hello"
I don't want to change the FileList but to change what will be adding from the FileList to the listBox and that is only the left side.
another problem might be with the listBox selected index :
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var item = ((ListBox)sender).SelectedItem;
var itemCast = (KeyValuePair<string, string>)item;
pictureBox1.Image = System.Drawing.Image.FromFile(itemCast.Value);
}
in one hand i don't want to see in the listBox the right side the values in the other hand i want the selected index event to be working.
A dictionary maps keys to values. What you call "left part/side" is actually the key, and the other element is the value.
C# Dictionary has a property: Keys which returns only the keys in the dictionary (e.g. your "hello" string).
Therefore you can use:
listBox1.DataSource = FileList.Keys.ToList();
Note that if you ever need only the values (e.g. "d:\test\test1.txt" etc.), Dictionary has a similar property: Values.
I'm guessing that, when the user selects a key, you're going to want to get the corresponding value. In that case, rather than just binding the keys, bind the whole Dictionary:
myListBox.DisplayMember = "Key"
myListBox.ValueMember = "Value"
myListBox.DataSource = myDictionary.ToArray()
Each item is a KeyValuePair, which has Key and Value properties. The code above will display the keys and then, when the user selects an item, you can get the corresponding value from the SelectedValue property.
Note that data-binding like this requires an IList, while the Dictionary only implements ICollection. For that reason, you need to call ToArray or ToList to create an IList for binding.
I have a ListBox (sortedListBox) which I have populated like this by the items in a Combobox (allItemsComboBox):
int index = sortedListBox.FindString(allItemsComboBox.Text, -1);
if (index == -1)
{
var item=new { Text = allItemsComboBox.Text , Value = allItemsComboBox.Value};
sortedListBox.Items.Add(item);
}
The DisplayedMember of sortedListBox is "Text" and ValueMember of it is "Value".
Now I want to iterate through all items in the ListBox and get its values:
public static string ListBoxToString(ListBox lb)
{
List<string> values = new List<string>();
for (int i = 0; i < lb.Items.Count; i++)
{
values.Add(lb.Items[i].ToString());
}
string result = String.Join(",", values);
return result;
}
In this line: values.Add(lb.Items[i].ToString()); I get:
{ Text = "Size" , Value = "cte1.Size"}
I just want to have the value , which is "cte1.Size"
How can I iterate through the items in the ListBox and get the ValueMember of these?
I don't know that there's any way to ask the ListBox to evaluate the ValueMember for you in that way... and because you're using an anonymous type, it becomes harder to get the value.
Options:
Use a named type instead, and cast each item to that
Use dynamic typing
For example:
public static string ListBoxToString(ListBox lb)
{
var values = lb.Items
.Cast<dynamic>()
.Select(x => x.Value.ToString());
return string.Join(",", values);
}
Dynamic typing provides the most immediate fix, but I'd strongly encourage you to consider using a custom type. (It needn't take more than a few lines to write.)
There are two problems with your approach:
1.) The ListBox stores items as a collection of objects which means accessing them with listBox.Items[idx] will only give you back an object and not the actual type. You could get around that with casting it to the appropriate type but it won't work in your case because of the next point.
2.) You create your items as anonymous objects with var item = new { ... }. You can't cast to this kind of type. You could use the dynamic keyword to get around that but I wouldn't do that as you lose type safety.
What you could do is create a simple class for the date you want to store and use that instead of an anonymous type:
class MyData
{
public string Text { get; set; }
public string Value { get; set; }
}
I have a ComboBox with the following code:
private void comboBox1_TextChanged(object sender, EventArgs e)
{
using (var service = WebServiceHelper.GetCoreService())
{
string physicianXml = service.SearchPhysicians(SessionInfo.Current.ClientCode, SessionInfo.Current.MachineName,
SessionInfo.Current.Username, comboBox1.Text);
var physicians = PhysicianItemList.FromXml(physicianXml);
AutoCompleteStringCollection autoCompleteStringCollection = new AutoCompleteStringCollection();
foreach (var physician in physicians.Items)
{
autoCompleteStringCollection.Add(physician.LastName + ", " + physician.FirstName);
}
comboBox1.AutoCompleteCustomSource = autoCompleteStringCollection;
comboBox1.Select(comboBox1.Text.Length, 0);
}
}
Basically, a user types the first few characters of a physician's name and it should populate the auto-complete list with the top 100 matching records. It works great, but I need to associate it back to a key (either the PK from the table, or the Physician's NPI number). It seems the AutoCompleteStringCollection doesn't support keys. Can anyone suggest a way of doing this? There are approximately 7 million records in the table, so I don't want to prepopulate the ComboBox.
Thanks
When you build your AutoCompleteStringCollection, build a Dictionary<String, int> for the name, id pairs as well. Then use some event (textbox validation or user submit/save click) to lookup and set the id. You could store the dictionary on the textbox Tag.
Edit
For some reason I thought you were working with a textbox control. Forget about the AutoCompleteStringCollection and just build a Dictionary<String, int>. For the combobox set your autocompletesource to ListItems, set the combobox display name and value and set the datasource to the dictionary.
combobox.DisplayMember = "key";
combobox.ValueMember = "value";
combobox.AutocompleteSource = AutocompleteSource.ListItems;
combobox.DataSource = myDictionary;
However you should only populate the datasource and autocomplete once when the user enters n characters in the combobox, otherwise it gets buggy. I tried to use this for a dynamic autocomplete once (eg the list clears if the user clear the text and retypes), but I had to forget about the combobox and use a hybrid textbox listbox approach much like this user
It looks like your problem is that AutoCompleteStringComplete was made specifically for strings (hence, the name).
You may want to look into the parents (IList, ICollection, IEnumerable) and see if you can homebrew something templated toward a key/value struct.
Too late but maybe someone will use this code :
this.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
RNProveedor rnProveedor = new RNProveedor();
var listaProveedores = rnProveedor.Buscar();
Dictionary<int, String> dicTemp = new Dictionary<int, string>();
foreach (var entidad in listaProveedores)
{
dicTemp.Add(entidad.ProvNro, entidad.ProNombre);
}
this.DataSource = new BindingSource(dicTemp, null);
this.DisplayMember = "Value";
this.ValueMember = "Key";
And to select the value
public int GetValorDecimal()
{
KeyValuePair<int, string> objeto = (KeyValuePair<int, string>)this.SelectedItem;
return objeto.Key;
}
With this example you won't have any problem with duplicated strings as the examples above
Basically I need to populate a listBox's .Text value with a string and its .Value value with an int.
By doing this:
lbUsers.DataSource = new UserManagerBO().GetGlobalUserList();
lbUsers.DataBind();
This assigns a string to both .Value and .Text.
Now I know GetGlobalUserList() returns a string[] which is why I'm getting the behaviour above, so how to go about returning the int values along with the string ones? Maybe go 2D array? And then how to bind those results to the listbox?
Option 1
Let that method return string[] and for value pick SelectedIndex.
Option 2
Create a custom class as Damith answers.
Option 3
A Dictionary<int, string> will suffice.
Dictionary Keys for ListBox Value and Dictionary Values for ListBox Text.
Say this is the dictionary returned by your method
//Adding key value pair to the dictionary
Dictionary<int, string> dStudent = new Dictionary<int, string>();
dStudent.Add(0, "Eena");
dStudent.Add(1, "Meena");
dStudent.Add(2, "Deeka");
dStudent.Add(3, "Tom");
dStudent.Add(4, "Dick");
dStudent.Add(5, "Harry");
dStudent.Add(6, "Yamla");
dStudent.Add(7, "Pagla");
dStudent.Add(8, "Dewana");
dStudent.Add(9, "Guru");
dStudent.Add(10, "Sholay");
Step 2:
Now it's time to bind a Dictionary pair with your listbox. The following code binds to listbox.
//binding to the list
lst.DataTextField = "Value";
lst.DataValueField = "Key";
lst.DataSource = dStudent;
lst.DataBind();
Create custom class with user properties. this can be re used when you deal with Global Users
public class CustomClass()
{
public int ID { get; set; }
public int Name { get; set; }
}
return collection of CustomClass objects from GetGlobalUserList(), you need to change the signature and logic of GetGlobalUserList method. Ones you done that,
lbUsers.DataSource = new UserManagerBO().GetGlobalUserList();
set DataTextField and DataValueField of your listbox
lbUsers.DataTextField = "Name";
lbUsers.DataValueField = "ID";
lbUsers.DataBind();
I'm binding a Dictionary to a drop down list.
Say for example I have the following items in dictionary:
{"Test1", 123}, {"Test2", 321}
I'd like the drop down text to take the following format:
Test1 - Count: 123
Test2 - Count: 321
I was going along the following path with no luck:
MyDropDown.DataTextFormatString = string.Format("{0} - Count: {1}", Key, Value);
Thank you :)
You could create a projection view by using LINQ on your dictionary and create an anonymous type to hold your custom formatting.
Dictionary<string, int> values = new Dictionary<string, int>();
values.Add("First", 321);
values.Add("Second", 456);
values.Add("Third", 908);
var displayView = from display in values
select new { DisplayText = display.Key + " Count: " + display.Value };
DropDownList1.DataSource = displayView;
DropDownList1.DataTextField = "DisplayText";
DropDownList1.DataBind();
I don't think that the DropDownList does support DataTextFormatString s that concat a String like you want to do it. As far as I know, you can only use format strings for numbers and dates. (For examples see here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listcontrol.datatextformatstring.aspx)
You can either do it the way ChristiaanV proposes (anonymous type), or you use your own POCO class (class only containing properties).
Be aware that using anonymous types have a limited scope. You can't usem them in a BusinessLayer-Assembly and have the GUI-Assembly use the result, because the ability of returning an anonymous type from a method are very limited.
I'd suggest you do something like this:
public class MyPOCO
{
public int MyPrimaryKey {get;set;}
public String DisplayString {get;set;}
}
Create a List<MyPOCO> in your code and bind it to the DataSource property.
Set the DataValueField to MyPrimaryKey and the DataTextField to DisplayString
If you are having problems with your databinding on postbacks, you can do the following:
Create a method that returns a List<MyPOCO>
Create a ObjectDataSource and use the wizard to select the methods you created in 1.
Assign the ID of the ObjectDataSource to the DataSourceID of the DropDownList.
You cannot use string.Format in
DataTextFormatString
Try the following code.
Dictionary<string, int> s = new Dictionary<string, int>();
s.Add("Test1", 123);
s.Add("Test2", 321);
foreach(KeyValuePair<string,int> temp in s)
{
DropDownList1.Items.Add(new ListItem(string.Format("{0} - Count: {1}", temp.Key, temp.Value),temp.Value.ToString()));
}