I've followed the advice given here : How to bind Enum to combobox with empty field in C# but it gave me some unusable content:
which is not what I would like to see... Here's the code I used to bind:
comboBox2.DataSource = GetDataSource(typeof (MessageLevel), true);
And here's the background:
public enum MessageLevel
{
[Description("Information")]
Information,
[Description("Warning")]
Warning,
[Description("Error")]
Error
}
----
public static string GetEnumDescription(string value)
{
Type type = typeof(MessageLevel);
var name = Enum.GetNames(type).Where(f => f.Equals(value, StringComparison.CurrentCultureIgnoreCase)).Select(d => d).FirstOrDefault();
if (name == null)
{
return string.Empty;
}
var field = type.GetField(name);
var customAttribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
return customAttribute.Length > 0 ? ((DescriptionAttribute)customAttribute[0]).Description : name;
}
public static List<object> GetDataSource(Type type, bool fillEmptyField = false)
{
if (type.IsEnum)
{
var data = Enum.GetValues(type).Cast<Enum>()
.Select(E => new { Key = (object)Convert.ToInt16(E), Value = GetEnumDescription(E.ToString()) })
.ToList<object>();
var emptyObject = new { Key = default(object), Value = "" };
if (fillEmptyField)
{
data.Insert(0, emptyObject); // insert the empty field into the combobox
}
return data;
}
return null;
}
How can I make a correct binding and adding one empty entry?
So the solution is to also set DisplayMember and ValueMember properties on ComboBox, so that it will know how to treat Key and Value properties.
comboBox2.DataSource = GetDataSource(typeof (MessageLevel), true);
comboBox2.DisplayMember = "Value";
comboBox2.ValueMember = "Key";
Related
cant select combo item by value after its passed to form. Comb is populated properly i get all the customers displayed by Text.
public OrderViewerForm(string orderId)
{
InitializeComponent();
PopulateCustomerCombobox();
PopulateForm(orderId);
PopulateProductsTable();
}
private void PopulateForm(string orderId)
{
OrderModel order = db.LoadOrder(orderId);
List<ProductsOrderedModel> productsOrdered = db.ProductsOrdered_Load(orderIdValue.Text);
orderIdValue.Text = order.Id.ToString();
customerIdValue.Text = order.CustomerId.ToString();
customerIdCombo.SelectedValue = order.CustomerId;
}
private void PopulateCustomerCombobox()
{
customerIdCombo.Items.Clear();
List<CustomerModel> customer = db.CustomerGet_All();
foreach (CustomerModel c in customer)
{
customerIdCombo.DisplayMember = "Text";
customerIdCombo.ValueMember = "Value";
customerIdCombo.Items.Add(new { Text = c.FullInfo, Value = c.Id });
}
}
At the end order.CustomerId is set properly but customerIdCombo.SelectedValue stays null. What am I doing wrong?
I would suggest switching to databinding here. Your foreach looks weird by the way.
private void PopulateCustomerCombobox()
{
customerIdCombo.DisplayMember = "Text";
customerIdCombo.ValueMember = "Value";
customerIdCombo.DataSource = db.CustomerGet_All().Select(c=> new { Text = c.FullInfo, Value = c.Id});
}
Thinking about it you may want to drop the hole anonymous type thing. why not simply bind the list you get from CustomerGet_All?
Im my model I have decleared value from wich I have to group, like this:
Note! Sender value is multivalued type
private ICollection<string> _send;
[SolrField("sender")]
public ICollection<string> Sender
{
get
{
if (_send == null)
{
return new Collection<string> { "" };
}
else
{
return _send;
}
}
set { _send = value; }
}
In my controller where I call Linq group code is:
var groups = matchingSpremenljivke.GroupBy(s => s.Sender);
foreach (IGrouping<string, SolrVariables> groups in gruph)
{
...
}
In foreach sentence I get this error:
"Unable to cast type 'Grouping
[System.Collections.Generic.ICollection'1
[Sytem.String],MySoulution.Models.SolrVariables]'to type
'System.Linq.IGrouping'2[System.String,MySolution.Models.SolrVariables]'
This error shows only for variables that are multivalued, for non-multivalued type of variables this error is not shown.
my all code look like this now:
var grupe = matchingSpremenljivke.GroupBy(s => s.Sender);
foreach (IGrouping<ICollection<string>, SpremenljivkeSolr> grupa in grupe)
{
List<SpremenljivkeSolr> tmpList = new List<SpremenljivkeSolr>();
foreach (SpremenljivkeSolr tmpSolr in grupa)
{
tmpList.Add(tmpSolr);
}
SpremenljivkeSolr spremenljivkeSolr = new SpremenljivkeSolr();
spremenljivkeSolr.Internal = tmpList[tmpList.Count - 1].Internal;
spremenljivkeSolr.Exchangetimestamp = tmpList[tmpList.Count - 1].Exchangetimestamp;
spremenljivkeSolr.Order = tmpList[0].Order;
spremenljivkeSolr.Exchangetimestamp2 = tmpList[0].Exchangetimestamp;
spremenljivkeSolr.MsgT = tmpList[0].MsgT;
spremenljivkeSolr.Sender = tmpList[tmpList.Count - 1].Sender;
seznam.Add(spremenljivkeSolr);
}
Thanks for help!
Since the type of Sender property is ICollection<string>, this query:
var groups = matchingSpremenljivke.GroupBy(s => s.Sender);
returns an IGrouping<ICollection<string>,SolrVariables> not IGrouping<string, SpremenljivkeSolr>. Change string to ICollection<string> in foreach or use var.
Also are you sure you want to group your values based on an ICollection<T> without providing an IEqualityComparer<T> implementation ?
I am trying to sort an ObservabkeCollection object containing the following class
public Favourites(string title=null, string uri=null, string folder=null, bool delete=false)
{
this.pageTitle = title;
this.pageURI = uri;
this.folder = folder;
this.deleteEnabled = delete;
}
I am trying to sort by folder then by uri. While the uri and title can be null, in my case I always assign them with something not null. However the folder property can be null.
My code to sort
private void sortCollectionFolderFirst()
{
IEnumerable<Favourites> sort;
ObservableCollection<Favourites> tempSortedFavourites = new ObservableCollection<Favourites>();
tempFavs.Clear();
tempFavs = settings.FavouritesSetting;
sort = tempFavs.OrderByDescending(item => item.Folder).ThenBy(item => item.PageURI);
foreach (var item in sort)
{
tempSortedFavourites.Add(item);
}
settings.FavouritesSetting = tempSortedFavourites;
}
The sorting is fine when the class item is
this.pageTitle = sometitle;
this.pageURI = someuri;
this.folder = null;
this.deleteEnabled = false or true;
But sort returns empty when it encounters an item with the following content
this.pageTitle = sometitle;
this.pageURI = someuri;
this.folder = somefoldername;
this.deleteEnabled = false or true;
Why is that?
So I've been looking to set a default value for my combobox. I found a few things but none of them seem to work.
Actually, it works if I create a simple combobox and use comboBox1.SelectedIndex = comboBox1.Items.IndexOf("something") but once I dynamically generate the contents of the comboboxes, I can't get it to work anymore.
This is how I fill my combo box (located in the class's constructor);
string command = "SELECT category_id, name FROM CATEGORY ORDER BY name";
List<string[]> list = database.Select(command, false);
cbxCategory.Items.Clear();
foreach (string[] result in list)
{
cbxCategory.Items.Add(new ComboBoxItem(result[1], result[0]));
}
I can't seem to get it to work to set a default value, like if I place cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf("New") below the above code, it won't work.
WinForms, by the way.
Thank you in advance.
cbxCategory.SelectedIndex should be set to an integer from 0 to Items.Count-1 like
cbxCategory.SelectedIndex = 2;
your
cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf("New")
should return -1 as long as no ComboboxItem mutches the string ("New");
another solution though i don't like it much would be
foreach(object obj in cbxCategory.Items){
String[2] objArray = (String[])obj ;
if(objArray[1] == "New"){
cbxCategory.SelectedItem = obj;
break;
}
}
perhaps this also requires the following transformation to your code
foreach (string[] result in list)
{
cbxCategory.Items.Add(result);
}
I haven't tested the code and i am not sure about the casting to String[2] but something similar should work
It looks like you're searching the cbxCategory.Items collection for a string, but it contains items of type ComboBoxItem. Therefore the search will return -1.
You can use LINQ.
//string command = "SELECT category_id, name FROM CATEGORY ORDER BY name";
//List<string[]> list = database.Select(command, false);
// sample data...
List<string[]> list = new List<string[]> { new string[] { "aaa", "bbb" }, new string[] { "ccc", "ddd" } };
cbxCategory.Items.Clear();
foreach (string[] result in list)
{
cbxCategory.Items.Add(new ComboBoxItem(result[1], result[0]));
}
ComboBoxItem tmp = cbxCategory.Items.OfType<ComboBoxItem>().Where(x => x.ResultFirst == "bbb").FirstOrDefault();
if (tmp != null)
cbxCategory.SelectedIndex = cbxCategory.Items.IndexOf(tmp);
ComboBoxItem class:
class ComboBoxItem
{
public string ResultFirst { get; set; }
public string ResultSecond { get; set; }
public ComboBoxItem(string first, string second)
{
ResultFirst = first;
ResultSecond = second;
}
}
Here's my simple solution
var list = comboBox1.Items.Cast<string>().ToList();
cbxCategory.SelectedIndex = list.FindIndex(c => c.StartsWith("test"));
My solution:
int? defaultID = null;
foreach (DataRow dr in dataSource.Tables["DataTableName"].Rows)
{
if ((dr["Name"] != DBNull.Value) && ((string)dr["Name"] == "Default Name"))
{
defaultID = (int)dr["ID"];
}
}
if (defaultID != null) comboBox.SelectedValue = defaultID;
I have a combobox with objects of Foo type, here is the Foo class:
public class Foo
{
public string name { get; set; }
public string path { get; set; }
}
The Foo.name is the displayed text in the combobox and Foo.path is the value of the selected option.
I want to delete an option from the combobox after some operation I made.
I've tried these ways:
1
comboBox2.Items.Remove(#comboBox2.Text);
2
comboBox2.Items.Remove(#comboBox2.SelectedValue.ToString());
3
Foo ToDelete = new Foo();
ToDelete.name = #comboBox2.Text;
ToDelete.path = #comboBox2.SelectedValue.ToString();
comboBox2.Items.Remove(ToDelete);
Nothing works for me. : / How to do this?
UPDATE
This is how I'm initializing my combobox:
string[] filePaths = Directory.GetFiles(sites.paths[comboBox1.SelectedIndex]);
List<Foo> combo2data = new List<Foo>();
foreach (string s in filePaths)
{
Foo fileInsert = new Foo();
fileInsert.path = s;
fileInsert.name = Path.GetFileName(s);
combo2data.Add(fileInsert);
}
comboBox2.DataSource = combo2data;
comboBox2.ValueMember = "path";
comboBox2.DisplayMember = "name";
comboBox2.Items.Remove(comboBox2.SelectedValue); will only remove from the combobox, not from the datasource bound to the combobox. You may remove it from the datasource and re-bind the datasource.
Use ComboBox.SelectedIndex property.
For example: let me have comboBox1 added to the form. In the delete button:
if (comboBox1.SelectedIndex >= 0)
comboBox1.Items.RemoveAt(comboBox1.SelectedIndex);
combox1.Remove(takes an object)
Object selectedItem = comboBox1.SelectedItem;
So you cna do it this way combox1.Remove(selectedItem);
Suppose you want to Remove Items by Index:
combo2data.RemoveAt(0); //Removing by Index from the dataSource which is a List
//Rebind
comboBox2.DataSource = null;
comboBox2.DataSource = combo2data;
comboBox2.ValueMember = "path";
comboBox2.DisplayMember = "name";
Suppose you want to Remove by seraching for a member value
Foo item = combo2data.Where(f => f.name.Equals("Tom")).FirstOrDefault();
if (item != null)
{
combo2data.Remove(item);
comboBox2.DataSource = null;
comboBox2.DataSource = combo2data;
comboBox2.ValueMember = "path";
comboBox2.DisplayMember = "name";
}
These 2 commands will remove an item from your data source.
list.Remove((Foo)comboBox1.SelectedItem);
or
list.Remove(list.Find(P=>P.name == comboBox1.SelectedText));
I think the secret is to first attribute null to the datasource and after rebind to a modified collection:
int idToRemove = 1;
var items = (cbx.DataSource as List<MyEntity>);
items.RemoveAll(v => v.Id == idToRemove);
rebindCombobox(cbx, items, "Name", "Id");
private void rebindCombobox(ComboBox cbx, IEnumerable<Object> items, String displayMember, String valueMember)
{
cbx.DataSource = null;
cbx.DisplayMember = displayMember;
cbx.ValueMember = valueMember;
cbx.DataSource = items;
}
Perhaps delete all items in the Combobox with
comboBox.Items.Clear();