In my WinForms / C# application, I can choose either Combobox.Text or Combobox.SelectedText to return the string value of what's been selected. What's the difference, and when would I choose one over the other?
SelectedText is what's highlighted. Depending on the DropDownStyle property, users can select a part of the visible text.
For example, if the options are:
Democrat
Republican
Independent
Other
A user can select the letters "Dem" in Democrat - this would be the SelectedText. This works with the ComboBoxStyle.Simple or ComboBoxStyle.DropDown, but NOT with ComboBoxStyle.DropDownList, since the third style does not allow selecting a portion of the visible item (or adding new items).
http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.selectedtext.aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.comboboxstyle.aspx
However, using the Text property, you can pre-select an option (by setting the Text to "Other", for example, you could select the last item.)
http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.text.aspx
I find it easier to see the difference using a text box:
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "Text in combo box 1";
textBox2.Text = "Text in combo box 2";
button1.Focus();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(textBox2.SelectedText);
}
In textbox2, select part of the text and click the button.
I've used this before for primitive spell checkers, when you only want to highlight part of the textbox (not the whole value)
Try this one. It helps when the DropDownStyle property is set to DropDownList.
public string GetProdName(int prodID)
{
string s = "";
try
{
ds = new DataSet();
ds = cmng.GetDataSet("Select ProductName From Product where ProductID=" + prodID + "");
if (cmng.DSNullCheck(ds) && cmng.DSRowCheck(ds))
{
s = ds.Tables[0].Rows[0][0].ToString();
}
}
catch {
}
return s;
}
In the click event:
lblProduct.Text = GetProdName((int)ddlProduct.SelectedValue);
If you want to read an item text which is in a combobox, you can use [comboboxname].SelectedItem.ToString().
If you want to read an item value, use [comboboxname].SelectedValue.
Related
In my VS2015 Winform app, there is one DataGridView control bound to a BindingSource that is bound to a SQL database. The Grid has four columns: ID, URL, Name, Type. The URL column is DataGridViewLinkColumn whose ReadOnly property, by default, is set to False. I can edit the Name and Type columns but URL columns shows as ReadOnly. Why? How can I make URL column editable?
As Reza stated:
DataGridViewLinkColumn is not editable.
Therefore, to edit a cell in such a column you'll have to convert it to a DataGridViewTextBoxCell as needed. For instance, if I have subscribed to DataGridView.CellContentClick to handle clicking on a link, then I would handle CellDoubleClick for the cell conversion:
private void DataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex] == this.dataGridView1.Columns["URL"])
{
this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] = new DataGridViewTextBoxCell();
this.dataGridView1.BeginEdit(true);
}
}
Once you've entered your value and left the cell, you should then use CellValidated to verify that the new value is a URI before converting the cell back to a DataGridViewLinkCell:
private void DataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex] == this.dataGridView1.Columns["URL"])
{
DataGridViewCell cell = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
if (Uri.IsWellFormedUriString(cell.EditedFormattedValue.ToString(), UriKind.Absolute))
{
cell = new DataGridViewLinkCell();
}
}
}
Caveat:
This only worked for me when the data for the "URL" column were strings and thus after binding, the column defaulted to a DataGridViewTextBoxColumn - forcing a manual conversion to link cells to begin with:
private void DataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow r in dataGridView1.Rows)
{
if (Uri.IsWellFormedUriString(r.Cells["URL"].Value.ToString(), UriKind.Absolute))
{
r.Cells["URL"] = new DataGridViewLinkCell();
}
}
}
Setting up the "URI" column as a DataGridViewLinkColumn from the beginning allowed for the conversion of cells to TextBox type successfully. But when converting back to link cells, debugging showed the conversion to happen, but the cell formatting and behavior failed.
I have a ComboBox (ToolStripCombobox, to be more precise) filled with items of type KeyValuePair<Int32, FontFamily>. I managed to have the Items beeing painted manually by using the DrawItem event. So every Item is painted with the FontFamily of the corresponding KeyValuePair. This works fine for the DropDownList, but when I select an Item out of the List and the list closes, the text in the ComboBox says something like "[21, [FontFamily: Name=Arial]]" which is most likely the result of SelectedItem.ToString().
Any ideas how to solve this problem?
here is the code of my custom DrawItem method:
private void fontComboBoxDrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
if ((e.State & DrawItemState.Focus) != 0)
{
e.DrawFocusRectangle();
}
Brush objBrush = null;
var itemToDraw = this.fontComboBox.Items[e.Index];
KeyValuePair<Int32, FontFamily> windowsFontItem = (KeyValuePair<Int32, FontFamily>)itemToDraw;
objBrush = new SolidBrush(e.ForeColor);
e.Graphics.DrawString(windowsFontItem.Value.Name, new Font(windowsFontItem.Value, e.Font.Size), objBrush, e.Bounds);
if (objBrush != null)
{
objBrush.Dispose();
}
objBrush = null;
}
Update:
It works as expected, when I set the DropDownStyle of the ComboBox to ComboBoxStyle.DropDownList
But I´d rather use ComboBoxStyle.DropDown, so you can edit the Text to search for Fonts.
I want to have a drop down list with 12 choices.
I found that ComboBox is what I need (if there is a better control kindly tell me).
I dragged and drop a combo box into a panel using VS2012 and then clicked on the left arrow that appears on the combo box. The following wizard shows:
As you can see, I am just able to type the name of the choice but not the value of it.
My question is how to get the value of these choices?
What I have tried
I built an array with the same length as the choices, so when the user selects any choice, I get the position of that choice and get the value from that array.
Is there a better way?
You need to use a datatable and then select the value from that.
eg)
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Description", typeof(string));
dt.Load(reader);
//Setting Values
combobox.ValueMember = "ID";
combobox.DisplayMember = "Description";
combobox.SelectedValue = "ID";
combobox.DataSource = dt;
You can then populate your datatable using:
dt.Rows.Add("1","ComboxDisplay");
Here, the DisplayMember(The dropdown list items) are the Descriptions and the Value is the ID.
You need to include a 'SelectedIndexChanged' Event on your combobox (If using VS then double click the control in Design Mode) to get the new values. Something like:
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
int ID = Combobox.ValueMember;
string Description = ComboBox.DisplayMember.ToString();
}
You can then use the variables in the rest of your code.
You cannot use the wizard to store values and text. To store DisplayText/Value pair the combobox needs to be connected to some data.
public class ComboboxItem
{
public string DisplayText { get; set; }
public int Value { get; set; }
}
There are two properties on the combobox - DisplayMember and ValueMember. We use these to tell the combobox that - show whats in DisplayMember and the actual value is in ValueMember.
private void DataBind()
{
comboBox1.DisplayMember = "DisplayText";
comboBox1.ValueMember = "Value";
ComboboxItem item = new ComboboxItem();
item.DisplayText = "Item1";
item.Value = 1;
comboBox1.Items.Add(item);
}
To get the value -
int selectedValue = (int)comboBox1.SelectedValue;
I have Datagrid and Text Box in my Form. Datagrid is showing me existing items in my stock. I use Text Box to search and set focus to that row which is matching with my Text Box. Now it is working fine when VirtualizingStackPanel.IsVirtualizing="false" but it is very slow and getting a lot RAM resource.
Here is my code for this.
public IEnumerable<Microsoft.Windows.Controls.DataGridRow> GetDataGridRows(Microsoft.Windows.Controls.DataGrid grid)
{
var itemsSource = grid.ItemsSource as IEnumerable;
if (null == itemsSource) yield return null;
foreach (var item in itemsSource)
{
var row = grid.ItemContainerGenerator.ContainerFromItem(item) as Microsoft.Windows.Controls.DataGridRow;
if (null != row) yield return row;
}
}
private void SearchBoxDataGrid_TextChanged(object sender, TextChangedEventArgs e)
{
var row = GetDataGridRows(AssortDataGrid);
/// go through each row in the datagrid
foreach (Microsoft.Windows.Controls.DataGridRow r in row)
{
DataRowView rv = (DataRowView)r.Item;
// Get the state of what's in column 1 of the current row (in my case a string)
string t = rv.Row["Ассортимент"].ToString().ToLower();
if (t.StartsWith(SearchBoxDataGrid.Text.ToLower()))
{
AssortDataGrid.SelectedIndex = r.GetIndex();
AssortDataGrid.ScrollIntoView(AssortDataGrid.SelectedItem);
break;
}
}
}
What I want is to make it VirtualizingStackPanel.IsVirtualizing="true" but in this case my method is not working. I know why it is not working, my code will work only for showing part of Datagrid.
What do you recommend? How to fix this issue? Any idea will be appreciated. If you give any working code it will be fantastic. I hope I could explain my problem.
Virtualization means that WPF will reuse the UI components, and simply replace the DataContext behind the components.
For example, if your Grid has 1000 items and only 10 are visible, it will only render around 14 UI items (extra items for scroll buffer), and scrolling simply replaces the DataContext behind these UI items instead of creating new UI elements for every item. If you didn't use Virtualization, it would create all 1000 UI items.
For your Search to work with Virutalization, you need to loop through the DataContext (DataGrid.Items) instead of through the UI components. This can either be done in the code-behind, or if you're using MVVM you can handle the SeachCommand in your ViewModel.
I did a little coding and make it work. If anyone needs it in future please, use it.
Firstly I am creating List of Products
List<string> ProductList;
Then on Load Method I list all my products to my Product List.
SqlCommand commProc2 = new SqlCommand("SELECT dbo.fGetProductNameFromId(ProductID) as ProductName from Assortment order by ProductName desc", MainWindow.conn);
string str2;
SqlDataReader dr2 = commProc2.ExecuteReader();
ProductList = new List<string>();
try
{
if (dr2.HasRows)
{
while (dr2.Read())
{
str2 = (string)dr2["ProductName"];
ProductList.Insert(0, str2.ToLower ());
}
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured while trying to fetch data\n" + ex.Message);
}
dr2.Close();
dr2.Dispose();
After that I did some changes in SearchBoxDataGrid_TextChanged
private void SearchBoxDataGrid_TextChanged(object sender, TextChangedEventArgs e)
{
int pos = 0;
string typedString = SearchBoxDataGrid.Text.ToLower();
foreach (string item in ProductList)
{
if (!string.IsNullOrEmpty(SearchBoxDataGrid.Text))
{
if (item.StartsWith(typedString))
{
pos = ProductList.IndexOf(item);
AssortDataGrid.SelectedIndex = pos;
AssortDataGrid.ScrollIntoView(AssortDataGrid.SelectedItem);
break;
}
}
}
}
Now it works when VirtualizingStackPanel.IsVirtualizing="true".
That is all.
I have a ComboBox:
<ComboBox Name="Gen2Fis" ItemsSource="{Binding Path=Table}" SelectionChanged="Gen2Fis_SelectionChanged" DisplayMemberPath="LongName">
The query used to fill this combobox is:
Select ShortName, LongName from Table;
Based on the item selected from this list I want call another method with the selected item, but I need to use the ShortName (that isn't displayed) instead of the LongName (which is).
How would I go about doing this? Can I somehow hide the shortname in the list?
My method for loading the combo box:
public void LoadFINamesIntoList(string mainDB)
{
XiphosStr.ConnectString = mainDB;
dbConnection = new MyDatabaseConnection(XiphosStr.ConnectString);
DataSet ds = dbConnection.ExecuteQuery(Queries.getFIs);
Gen2Fis.DataContext = ds.Tables[0].DefaultView;
}
My method for the selection change:
private void Gen2Fis_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string gen2fi = (XiphosDB2.SelectedItem as ComboBoxItem).Content.ToString();
Gen2Str.ConnectString = gen2fi;
DisplayGen2Users();
}
gen2fi will equal the long name, but I need the short name.
Thanks for any help.
Jason
use SelectedValuePath from combobox and set your value path just like the display member
<ComboBox Name="Gen2Fis" ItemsSource="{Binding Path=Table}" SelectionChanged="Gen2Fis_SelectionChanged" DisplayMemberPath="LongName" SelectedValuePath="ShortName">
and then in the selectionchanged event you would be able to use selectedValue .
private void Gen2Fis_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string gen2fi = ((ComboBox)sender).SelectedValue ;
Gen2Str.ConnectString = gen2fi;
DisplayGen2Users();
}