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()));
}
Related
I have the following code as part of a WPF I am creating:
Dictionary<string, string[]> storeDictionary = new Dictionary<string, string[]>();
private void populateDropbox()
{
storeDropDown.DataSource = new BindingSource(storeDictionary, null);
storeDropDown.DisplayMember = "Key";
storeDropDown.ValueMember = "Value";
storeDropDown.SelectedValue = 0;
}
Note: storeDropDown is name of the combobox.
How would I get storeDropdown.Valuemember to be the first element of the string[]?
Please bare in mind this is my first program and c# is my first programming language.
If you need more info let me know, thanks.
You say you are doing WPF but the ComboBox you are using comes from winforms.
So what are you actually working on?
Assuming you are using Winforms (the ComboBox of your example) here is my solution:
1 - Create a class to encapsulate your array of string and override the ToString() method
internal class CustomArrayOfStrings
{
public string[] _strings;
public override ToString()
{
return _strings[0];
}
}
Now your dictionary looks like something like this:
Dictionary<string, CustomArrayOfStrings> storeDictionary = new Dictionary<string, CustomArrayOfStrings>();
2- Then, to display the first element in your ComboBox you change
storeDropDown.DisplayMember = "Key";
to
storeDropDown.DisplayMember = "Value";
This will call the ToString methode of your Value wich is a CustomArrayOfStrings.
3 - If you want to manipulate the selected first element of your array, you can do it this way:
CustomArrayOfStrings selected = storeDropDown.SelectedValue as CustomArrayOfStrings;
string firstValue = selected._strings[0];
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've got a list of name-value pairs that I'm wanting to put in a nice report format. Is it possible to use this as a data source for a ReportViewer object? This is in WinForms and ASP.
I was able to convert the Dictionary to a DataTable and use that as the DataSource.
var table = new DataTable();
var kvps = dictionary.ToArray();
table.Columns.AddRange(kvps.Select(kvp => new DataColumn(kvp.Name)).ToArray());
table.LoadDataRow(kvps.Select(kvp => kvp.Value).ToArray(), true);
bindingSource.DataSource = table;
VoilĂ
I believe you'll have to create a class to encapsulate the items you'd like to display in the report. See my answer to this question for how to bind a class to a report.
The code's in VB.NET but you'll be able to follow it quite easily.
I don't think that's not going to naturally bind in the ReportViewer. Just put them in a list of custom objects with the properties you want to bind to. It wouldn't be a lot of overhead (like a List.
Dictionaries are not suited as data source for lists. They are optimized for retrieving values for given keys. Nevertheless, you can retrieve the keys, the values and key/value pairs from the dictionary as follows:
var keys = dict.Keys;
var values = dict.Values;
var keyValuePairs = dict.OrderBy(x => x.Value);
foreach (KeyValuePair<string, int> item in keyValuePairs) {
Console.WriteLine("Key = {0}, Value = {1}", item.Key, item.Value);
}
I have the following object:
CrossTabDataObject
{
string RowName{get;set;};
int RowId{get;set;}
List<string> CellContents = new List <string>();
//Constructor..... etc.
}
I'm building a dynamic crosstab grid using GridView in asp.net 3.5
I wish to bind to CellContents[0] for dynamic column 1, CellContents[1] for dynamic column 2 (dynamic column 0 is the RowName field from the CrossTabDataObject) etc. I am using:
object boundValueObj = null;
Control ctrl = (Control)sender;
IDataItemContainer dataItemContainer = (IDataItemContainer)ctrl.NamingContainer;
boundValueObj = DataBinder.Eval(dataItemContainer.DataItem, strSelectedID);
This code is in the InstantiateIn function of the gridview as I'm creating drop down list templates in each cell of the crosstab.
I have code (not shown) that sets strSelectedID depending on the column being created.
When strSelectedID is equal to "RowName" for dynamic column [0] the DataBinder.Eval function works fine and sets boundValueObj as expected. The problem comes when strSelectedID is set to "CellContents[n]" where n is the Column Index.
DataBinder.Eval only works with properties and fields of objects. How do I get around this?
Thanks,
Rich.
OK - stupid mistake by me!
Changing:
CrossTabDataObject
{
string RowName{get;set;};
int RowId{get;set;}
List<string> CellContents = new List <string>();
//Constructor..... etc.
}
to:
CrossTabDataObject
{
string RowName{get;set;};
int RowId{get;set;}
List<string> CellContents{get;set;}
//Constructor
public CrossTabDataObject()
{
CellContents = new List<string>();
}
}
made all the difference. In other words I made CellContents a property of the class.
Rich.
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