I am trying to set the Text property of ComboBox on the basis of SelectedIndex but the problem is Text is becoming String.Empty after changing the Index of Combobox.
Each Item in ComboBox correspond to a string in DataTable having 2 columns Name, Description
What i need is when users select's a Name (Index Changes) when i want to show the Description of that in ComboBox
What i have tried :
private void tbTag_SelectionChangeCommitted(object sender, EventArgs e)
{
// get the data for the selected index
TagRecord tag = tbTag.SelectedItem as TagRecord;
// after getting the data reset the index
tbTag.SelectedIndex = -1;
// after resetting the index, change the text
tbTag.Text = tag.TagData;
}
How i have populated the Combobox
//load the tag list
DataTable tags = TagManager.Tags;
foreach (DataRow row in tags.Rows)
{
TagRecord tag = new TagRecord((string)row["name"], (string)row["tag"]);
tbTag.Items.Add(tag);
}
Helper Class Used :
private class TagRecord
{
public TagRecord(string tagName, string tagData)
{
this.TagName = tagName;
this.TagData = tagData;
}
public string TagName { get; set; }
public string TagData { get; set; }
public override string ToString()
{
return TagName;
}
}
I think that happens because -1 index in ComboBox means that no item was selected (msdn) and you are trying to change text of it. I would create one more element (at index 0) and make it change text depending on selection:
bool newTagCreated = false;
private void tbTag_SelectionChangeCommitted(object sender, EventArgs e)
{
TagRecord tag = tbTag.SelectedItem as TagRecord;
TagRecord newtag = null;
if (!newTagCreated)
{
newtag = new TagRecord(tag.TagData, tag.TagName); //here we change what is going to be displayed
tbTag.Items.Insert(0, newtag);
newTagCreated = true;
}
else
{
newtag = tbTag.Items[0] as TagRecord;
newtag.TagName = tag.TagData;
}
tbTag.SelectedIndex = 0;
}
Found a solution.
private void tbTag_SelectedIndexChanged(object sender, EventArgs e)
{
TagRecord tag = tbTag.SelectedItem as TagRecord;
BeginInvoke(new Action(() => tbTag.Text = tag.TagData));
}
Related
When I add an item into a listbox I also add a new line because I want there to be a blank line between each item added. When I remove a selected item I also want to remove the blank line I added otherwise I will end up getting 2 blank lines between each item this is the problem I am having so I thought if I could delete the selected item as well as the blank line above and below the selected item this would work. Is there a better approach to this?
ListBox1.Items.Remove(ListBox1.SelectedItem);
I have typed the items and differentiate what is the blank item and what is the value item. At the time of deleting I have the reference of both. It worked fine, see if it helps.
Here's an example:
Form:
private void Form1_Load(object sender, EventArgs e)
{
Data data = new Data { description = "Test1" };
listBox1.Items.Add(data);
data.BlankLine = new BlankItem();
listBox1.Items.Add(data.BlankLine);
data = new Data { description = "Test2" };
listBox1.Items.Add(data);
data.BlankLine = new BlankItem();
listBox1.Items.Add(data.BlankLine);
data = new Data { description = "Test3" };
listBox1.Items.Add(data);
data.BlankLine = new BlankItem();
listBox1.Items.Add(data.BlankLine);
data = new Data { description = "Test4" };
listBox1.Items.Add(data);
data.BlankLine = new BlankItem();
listBox1.Items.Add(data.BlankLine);
}
Event to delete the item on click:
private void listBox1_Click(object sender, EventArgs e)
{
if((listBox1.SelectedItem != null && listBox1.SelectedItem.GetType() != typeof(BlankItem)))
{
Data item = (Data)listBox1.SelectedItem;
listBox1.Items.Remove(item);
listBox1.Items.Remove(item.BlankLine);
}
}
Object Data
public class Data
{
public string description { get; set; }
public BlankItem BlankLine { get; set; }
public override string ToString()
{
return description;
}
}
Object BlankItem
public class BlankItem
{
public override string ToString()
{
return Environment.NewLine;
}
}
I wanted to try to implement the above functionality, but using a data-bound Listbox such that I make changes to the underlying list instead of the Listbox. If possible, use BindingList<T> instead of List<T> because it implements additional functionality specific to data binding.
The core is still the same, as each item added must also be followed by adding a string.Empty item. The same for removal, when an item is removed
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
var list = new BindingList<string>();
list.Add("ABC");
list.Add(string.Empty);
list.Add("GHK");
list.Add(string.Empty);
list.Add("OPQ");
listBox1.DataSource = list;
var binding = listBox1.BindingContext[list] as CurrencyManager;
listBox1.KeyDown += (s, ev) =>
{
if (ev.KeyData == Keys.Delete)
{
if (listBox1.SelectedItem != null && !listBox1.SelectedItem.Equals(string.Empty))
{
int index = listBox1.SelectedIndex;
if (index >= 0)
{
list.RemoveAt(index);
if (index < list.Count && list[index].Equals(string.Empty))
{
list.RemoveAt(index);
}
binding.Refresh();
}
}
}
if (ev.KeyData == Keys.Insert)
{
int index = listBox1.SelectedIndex;
if (index==-1 || list[index] == string.Empty)
{
index++;
}
list.Insert(index, "NEW " + (index + 1).ToString());
list.Insert(index+1, string.Empty);
}
};
}
}
press the [DEL] key to remove an item, and the [INS] key to add an item.
But I am not happy with this solution. I think there is a way to create a class that implements IListSource that you directly add/remove items and it creates a list with blanks in between automatically for binding.
I have bound to my combobox this simple class:
public class Company
{
public Guid CorporationId { set; get; }
public Guid TokenId { set; get; }
public string Name { set; get; }
}
And this is my binding:
private void FillCompaniesComboBox()
{
_doneLoadingComboBox = false;
comboBox_Companies.Items.Clear();
if (CurrentSettings.AllCompanies.Count == 0)
{
return;
}
bindingSource1.DataSource = CurrentSettings.AllCompanies;
comboBox_Companies.DataSource = bindingSource1.DataSource;
comboBox_Companies.DisplayMember = "Name";
comboBox_Companies.ValueMember = "CorporationId";
comboBox_Companies.SelectedIndex = 1;
_doneLoadingComboBox = true;
}
When I attempt to get the value of the selected item, I'm getting different results. Here is the code I am using to get my value:
private void comboBox_Companies_SelectedIndexChanged(object sender, EventArgs e)
{
if (!_doneLoadingComboBox && comboBox_Companies.SelectedIndex == -1)
{
return;
}
var value = (Company)comboBox_Companies.SelectedValue;
Console.WriteLine("Value: " + value.CorporationId);
}
Here is what is happening:
This one works at intended:
And this is were it is causing an issue:
Am I not retrieving the data correctly? I need the Company information that it is bound to.
Okay so here's what you need to do...
Assuming that your CurrentSettings.AllCompanies is an IList<Company> that you've already populated with data, here's what your code should look like:
public class ComboBoxItem {
// your class
private Company Comp;
}
private readonly BindingSource _bsSelectedCompany = new BindingSource();
private readonly ComboBoxItem _comboBoxItem = new ComboBoxItem();
// your main form method
public MainForm() {
// initialization code...
InitializeComponent();
// prevents errors in case your data binding objects are empty
ResetComboBox(comboBox1);
comboBox1.DataBindings.Add(new Binding(
"SelectedItem",
_bsSelectedCompany,
"Comp",
false,
DataSourceUpdateMode.OnPropertyChanged
));
comboBox1.DataSource = CurrentSettings.AllCompanies;
comboBox1.DisplayMember = "Name";
}
// simple method for resetting a given combo box to a default state
private static void ResetComboBox(ComboBox comboBox) {
comboBox.Items.Clear();
comboBox.Items.Add("Select a method...");
comboBox.SelectedItem = comboBox.Items[0];
}
By doing this, you're able to just use _comboBoxItem to safely get the information about your selected item without having to potentially Invoke it (in the case of accessing it on a separate thread).
I am trying to add an object ITEM with TEXT and VALUE to a ComboBox so I can read it later
public partial class Form1 : Form
{
ComboboxItem item;
public Form1()
{
InitializeComponent();
comboBox1.Items.Add(new ComboboxItem("Dormir", 12).Text);
}
private void button1_Click(object sender, EventArgs e)
{
ComboboxItem c = (ComboboxItem)comboBox1.SelectedItem;
label1.Text = c.Text;
label2.Text = c.Value.ToString();
}
}
The problem is, I cant add the full Item because isn't a string...and give an exception at beginning of click event
Extra information:
This ComboboxItem, its a class that I created with 2 parameters, string, and int
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
public ComboboxItem(string texto, double valor)
{
this.Text = texto;
this.Value = valor;
}
}
You could (should) set the displaymember and valuemember in another place, but...
public Form1()
{
InitializeComponent();
comboBox1.DisplayMember="Text";
comboBox1.ValueMember ="Value";
comboBox1.Items.Add(new ComboboxItem("Dormir", 12));
}
Create the ComboboxItem class and override the ToString method.
The ToString method will be called to visualize the item. By default, ToString() returns the typename.
public class ComboboxItem
{
public object Value{get;set;}
public string Text {get;set;}
public override string ToString(){ return Text; }
}
Then, you can do this:
var item = new CombobxItem { Value = 123, Text = "Some text" };
combobox1.Items.Add(item);
you dont need to add .Text at the end of ("text","value")
so add it as :
comboBox1.Items.Add(new ComboBoxItem("dormir","12"));
You are on the right lines by creating your own ComboBoxItem class.
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
}
There are two ways to use this, (Constructor aside):
Method 1:
private void button1_Click(object sender, EventArgs e)
{
ComboboxItem item = new ComboboxItem();
item.Text = "Item text1";
item.Value = 12;
comboBox1.Items.Add(item);
}
Method 2:
private void button1_Click(object sender, EventArgs e)
{
ComboboxItem item = new ComboboxItem
{
Text = "Item text1",
Value = 12
};
comboBox1.Items.Add(item);
}
Have you tried adding it like this instead? Then when ever you get the Item out just cast it as a ComboboxItem :)
...
var selectedItem = comboBox1.SelectedItem as ComboboxItem;
var myValue = selectedItem.Value;
...
Alternative KeyValuePair:
comboBox1.Items.Add(new KeyValuePair("Item1", "Item1 Value"));
Question based on returnign string value and other combobox answers..
ComboBox: Adding Text and Value to an Item (no Binding Source)
I want to make a ComboBox where the user can type an integer value into the text area, but the drop-down list contains several "defaults" values. For instance, the items in the drop-down list would be formatted like this:
Default - 0
Value 1 - 1
Value 2 - 2
What I want is that when the user selects an item (e.g. "Default - 0"), the ComboBox text will display only the number "0" rather than "Default - 0". The word "Default" is just informational text.
I have played with the following events: SelectedIndexChanged, SelectedValueChanged, and SelectionChangeCommitted, but I was not able to change the text of the ComboBox.
private void ModificationCombobox_SelectionChangeCommitted(object sender, EventArgs e)
{
ComboBox comboBox = (ComboBox)sender; // That cast must not fail.
if (comboBox.SelectedIndex != -1)
{
comboBox.Text = this.values[comboBox.SelectedItem.ToString()].ToString(); // Text is not updated after...
}
}
You can define a class for your ComboBox item, then create a List<ComboBoxItem> and use it as your Combobox.DataSource. With this you can set ComboBox.DisplayMember to a property you want displaying and still get reference to your object from ComboBox_SelectedIndexChanged():
class ComboboxItem
{
public int Value { get; set; }
public string Description { get; set; }
}
public partial class Form1 : Form
{
List<ComboboxItem> ComboBoxItems = new List<ComboboxItem>();
public Form1()
{
InitializeComponent();
ComboBoxItems.Add(new ComboboxItem() { Description = "Default = 0", Value = 0 });
ComboBoxItems.Add(new ComboboxItem() { Description = "Value 1 = 1", Value = 1 });
ComboBoxItems.Add(new ComboboxItem() { Description = "Value 2 = 2", Value = 2 });
comboBox1.DataSource = ComboBoxItems;
comboBox1.DisplayMember = "Value";
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var item = (ComboboxItem)((ComboBox)sender).SelectedItem;
var test = string.Format("Description is \'{0}\', Value is \'{1}\'", item.Description, item.Value.ToString());
MessageBox.Show(test);
}
}
[edit]
If you want to change displayed text when box toogles between DropDown states try this: (this is a concept, not sure how that would behave)
private void comboBox1_DropDown(object sender, EventArgs e)
{
comboBox1.DisplayMember = "Description";
}
private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
comboBox1.DisplayMember = "Value";
}
I'm having strange issues with the check box control in C# .Net
My code below shows all logic that is required - _itemsChecked is a private dictionary containing all of the _fixtures and whether they are true or false (checked or un checked)
What I want is to be able to search my check list whilst retaining those which have been checked previously. If a checked item is included in the search results I want it to be checked.
The code nearly works! But for some reason boxes are randomly checked here and there, and it appears to work through debug but when the screen returns to the control it then hasn't worked.
Sure I'm missing something very simple.
My logic is:
DataSource includes those which match the typed search query,
Iterate through this list and check if the Guid is true in the dictionary.
If it is true then we set it as checked.
Hope I have provided adequate information.
Many thanks in advance.
private void searchTextBox_KeyUp(object sender, EventArgs e)
{
lst.DataSource = _fixtures
.OrderBy(f =>
f.Description)
.Where(f =>
f.Description.ToLower().Contains(searchFixturesTextBox.Text.ToLower()))
.ToList();
lst.DisplayMember = "Description";
for (var i = 0; i < lst.Items.Count; i++)
if(_itemsChecked.Contains(new KeyValuePair<Guid, bool>(((Fixture)lst.Items[i]).Guid, true)))
lst.SetItemChecked(i, true);
}
void lst_ItemCheck(object sender, ItemCheckEventArgs e)
{
var selectedItem = ((ListBox) sender).SelectedItem as Fixture;
if (selectedFixtureItem != null)
_itemsChecked[selectedItem.Guid] = e.CurrentValue == CheckState.Unchecked;
}
So I put this together from a few examples I found. The majority of the work came from How do I make a ListBox refresh its item text?
public class Employee
{
public string Name { get; set; }
public int Id { get; set; }
public bool IsChecked { get; set; }
public override string ToString()
{
return Name;
}
}
public partial class Form1 : Form
{
// Keep a bindable list of employees
private BindingList<Employee> _employees;
public Form1()
{
InitializeComponent();
// Load some fake employees on load
this.Load += new EventHandler(Form1_Load);
// Click once to trigger checkbox changes
checkedListBox1.CheckOnClick = true;
// Look for item check change events (to update there check property)
checkedListBox1.ItemCheck +=
new ItemCheckEventHandler(CheckedListBox_ItemCheck);
}
// Load some fake data
private void Form1_Load(object sender, EventArgs e)
{
_employees = new BindingList<Employee>();
for (int i = 0; i < 10; i++)
{
_employees.Add(new Employee()
{ Id = i, Name = "Employee " + i.ToString() });
}
// Display member doesnt seem to work, so using ToString override instead
//checkedListBox1.DisplayMember = "Name";
//checkedListBox1.ValueMember = "Name";
checkedListBox1.DataSource = _employees;
// Another example databind to show selection changes
txtId.DataBindings.Add("Text", _employees, "Id");
txtName.DataBindings.Add("Text", _employees, "Name");
}
// Item check changed, update the Employee IsChecked property
private void CheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
CheckedListBox clb = sender as CheckedListBox;
if (clb != null)
{
Employee checked_employee = clb.Items[e.Index] as Employee;
if (checked_employee != null)
{
checked_employee.IsChecked = (e.NewValue == CheckState.Checked);
}
}
}
// Just a simple test that removes an item from the list, rebinds it
// and updates the selected values
private void btnChangeList_Click(object sender, EventArgs e)
{
_employees.RemoveAt(1);
checkedListBox1.DataSource = _employees;
for (var i = 0; i < checkedListBox1.Items.Count; i++)
{
Employee employee_to_check = checkedListBox1.Items[i] as Employee;
if (employee_to_check != null)
{
checkedListBox1.SetItemChecked(i, employee_to_check.IsChecked);
}
}
}
}