I have three textboxes that each contain a two-digit part of an ATA code. I want the UI to advance automagically to the next textbox when the Text is two digits long. Easy enough, I thought:
private void txtATAChapter_KeyUp(object sender, KeyEventArgs e)
{
var textbox = sender as TextBox;
if (textbox == null) return;
if (textbox.Text.Length == 2)
{ textbox.SelectNextControl(ActiveControl,true, true, true, true); } // breakpoint
}
... but it didn't work. The breakpoint hits on SelectNextControl when the text length is right, but the focus doesn't change. I've verified that all three of the textboxes have TabStop == true and sequential TabOrder numbers (26, 27 and 28). The ActiveControl unsurprisingly is set as the currently focused TextBox.
I'm out of ideas for what should be a dead simple thing to do.
You are trying to set the next control on the TextBox. You need to set it on its container, so try:
textbox.Parent.SelectNextControl(ActiveControl,true, true, true, true);
Related
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.
In my WPF application I have one datagrid and one textbox. In the textChanged event of the textbox, I put this:
myDatagrid.ItemsSource =
myListOfObjects.Where(item => item.Name.Contains(MyTextBox.Text)); //Filter
if (myDatagrid.Items.Count > 0) // If no itens, then do nothing
{
myDatagrid.SelectedIndex = 0; // If has at least one item, select the first
}
myDatagrid.Items.Refresh();
Note that I force the selection when the text changes, in the first row of the DataGrid.
But unfortunately, the color of the row does not change to blue, making it hard to see the selection.
I realy need this, because in the PreviewKeyDown event of the textbox I have this:
private void myTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Up)
{
if (!(myDataGrid.SelectedIndex <= 0))
{
myDataGrid.SelectedIndex--; // Go one position Up
}
}
if (e.Key == Key.Down)
{
if (!(myDataGrid.SelectedIndex == myDataGrid.Items.Count - 1))
{
myDataGrid.SelectedIndex++; // Go one position Down
}
}
}
So, when the textbox is focused and the user press the Up or the Down key, the selection does not appear to change.
Any idea of how I can make the selected item on the datagrid change it's color to blue?
Other thing: in my virtual machine, it works!! With the same code! How it's possible?
I think that is the aeroglass, but I change the theme to the Windows 7 Basic (same in the virtual machine) and still don't work.
Thanks, and sorry for my english.
Could you try using SelectedItem? you could always create a new property and bind to this and then set this item directly rather than using the selected index. Hopefully this would trigger any additional logic in the DataGrid control :)
//Declare property outside of method
public ObjectType SelectedItem { get; set; }
//Set datacontext on load
DataContext = this;
myDatagrid.ItemsSource = myListOfObjects.Where(item => item.Name.Contains(MyTextBox.Text)); //Filter
if (myDatagrid.Items.Count > 0) // If no itens, then do nothing
{
SelectedItem = myDatagrid.ItemSource[0]; // If has at least one item, select the first
}
myDatagrid.Items.Refresh();
Also don't forget to set your binding!
SelectedItem="{Binding SelectedItem}"
hope that helps!
I am using CheckedListBox , but I need to highlight individual items with different colors/fonts or some other highlighting method.
But it allows to change visual properties for the whole control only and not for individual items.
Additional Info:
I am using 2 such lists (because need checkboxes for easier selection) and 2 buttons (>> <<) for include/exclude type functionality. Is there any other better way to implement such whereby my requirement as above also gets fulfilled ?
I've only dabbled with DevExpress controls, but I think you have to subscribe to the DrawItem event and set the e.Handled property to true.
Something like this (CheckedListBox items with different colors):
private void checkedListBoxControl1_DrawItem(object sender, ListBoxDrawItemEventArgs e) {
CheckedListBoxControl clbControl = sender as CheckedListBoxControl;
ButtonState state = ButtonState.Normal;
if (clbControl.GetItemChecked(e.Index))
state = ButtonState.Checked;
ControlPaint.DrawCheckBox(e.Graphics, new Rectangle(e.Bounds.X, e.Bounds.Y, 15, 15), state);
string itemText = e.Item.ToString();
Rectangle textRect = new Rectangle(e.Bounds.X + 15, e.Bounds.Y, e.Bounds.Width - 15, e.Bounds.Height);
if ((e.State & DrawItemState.Selected) != 0) {
e.Graphics.FillRectangle(SystemBrushes.Highlight, textRect);
}
if (state== ButtonState.Checked)
e.Graphics.DrawString(itemText, e.Appearance.Font, new SolidBrush(Color.Red), textRect, e.Appearance.GetStringFormat());
else
e.Graphics.DrawString(itemText, e.Appearance.Font, new SolidBrush(Color.Black), textRect, e.Appearance.GetStringFormat());
e.Handled = true;
}
I have implemented WPF DataGrid Single-Click Editing from Codeplex.
In that solution, the clicked cell is focused and the row is selected to achieve
single-click editing of DataGrid. It worked great.
Here's the code:
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
{
if (!cell.IsFocused)
{
cell.Focus();
}
DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
if (dataGrid != null)
{
if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
if (!cell.IsSelected)
cell.IsSelected = true;
}
else
{
DataGridRow row = FindVisualParent<DataGridRow>(cell);
if (row != null && !row.IsSelected)
{
row.IsSelected = true;
}
}
}
}
}
But I also want my DataGrid to automatically exit editing mode (without hitting Enter key)
when a cell value is changed. For example, I have a combobox in the cell when in edit mode. When user selects a value in combobox, it will automatically databind the selected value. But then the user still need to click Enter to exit edit mode. How can I exit edit mode automatically?
I've tried listening for property changes and call CommitEdit function of DataGrid to exit edit mode automatically. Works great and here's the code:
void _gameCompareViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "End Edit")
{
AlignGrid.CommitEdit();
}
}
But now the Single-Click editing feature will not work for the current cell.
I have to click a different row first in order for it to work.
I think what I want is when CommmitEdit is called, it automatically selects a
different row. (Like when you hit Enter, it will go to the next row)
Any suggestions guys? Please show me codes on how to do this. Im running out of time here for my project.
Thanks for the help.
to flip from cell editing template back to cell template:
dataGrid.CancelEdit();
I desperately try to figure how to change the background color of a single cell in a winforms dataGridView. I have two columns: if i change content in the second column, i want the cell in the first column of this row to change the background accordingly.
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex != 0 || e.RowIndex == -1)
return;
if (dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString() == "Red")
e.CellStyle.BackColor = Color.Red;
else
e.CellStyle.BackColor = Color.White;
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != 1 || e.RowIndex == -1)
return;
// dataGridView1.Rows[e.RowIndex].Cells[0]. ???
}
The first event handler sets the backColor of the cells in the first column if they are painted. The second event handler should tell the first cell to paint if the value is changed. If i change the columns width it paints the correct color, so the first handler does the work. But how to trigger the cell painting?
Thanx for help.
I would have thought that the edit would have triggered a repaint, but if that event isn't being run after the edit then you should be able to force the issue with something like:
dataGridView1.InvalidateCell(e.RowIndex, 1);
OK, here is the bad hack:
If i insert
var x = dataGridView1.Columns[0].DefaultCellStyle;
dataGridView1.Columns[0].DefaultCellStyle = null;
dataGridView1.Columns[0].DefaultCellStyle = x;
in the CellValueChanged event handler, the whole first column is repainted. So my cell is repainted as well. But that't dirty, isnt't it?
You have to create a new cell style object, set it to the color you want and then apply it to the current cell.
private DataGridViewCellStyle CellStyleGreenBackgnd;
CellStyleGreenBackgnd.BackColor = Color.LightGreen;
dataGridView.CurrentCell.Style.ApplyStyle(CellStyleGreenBackgnd);
Try this.
dataGridView1.Rows[indexhere].Cells[indexhere].Style.ForeColor = Color.Yellow;