Combobox appearance - c#

Can I change the appearance of a Winforms ComboBox so that a Combobox with DropDownStyle = DropDownList looks more like one that is DropDownStyle = DropDown. The functional difference between them is that the former doesn't allow for user entered values, the problem is that it's default color scheme looks grayed out and doesn't match with textboxes on the same dialog.

you can get DropDown appearance from DropDownList style by changing DrawMode property to DrawMode.OwnerDrawFixed and handling item painting by yourself (thankfully, that's easy). Sample class, implementing this idea:
public class ComboBoxEx : ComboBox
{
public ComboBoxEx()
{
base.DropDownStyle = ComboBoxStyle.DropDownList;
base.DrawMode = DrawMode.OwnerDrawFixed;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
e.DrawBackground();
if(e.State == DrawItemState.Focus)
e.DrawFocusRectangle();
var index = e.Index;
if(index < 0 || index >= Items.Count) return;
var item = Items[index];
string text = (item == null)?"(null)":item.ToString();
using(var brush = new SolidBrush(e.ForeColor))
{
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
e.Graphics.DrawString(text, e.Font, brush, e.Bounds);
}
}
}

You could try to change the FlatStyle property and see if you get something more to your liking. If you really want it to look like it does with DropDownStyle set to DropDown, you could set the DropDownStyle to DropDown and eat the KeyPress event:
private void comboBox1_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
Still, I would probably not do this as the appearance of the ComboBox is a visual cue to the user indicating whether they should be able to type in the text area or not.

Related

Is select the one subitem without full row possible? C# [duplicate]

I am trying to get the selected ListViewItem index, so that when the user clicks on a particular row, such as row 2, I want the clicked cell's text to be set to a TextBox's text.
I also want to highlight only this cell, ideally using the regular selection ListView uses, or do I need to create a class that inherits from ListView to do this?
Something like this:
You can draw yourself the ListViewItem.ListViewSubItem selected, owner-drawing the Control (set ListView.OwnerDraw = true), then handle the ListView.DrawSubItem event.
The ListView.DrawColumnHeader event can use default values.
▶ I'm using TextRenderer since this is the default renderer. If you use Graphics.DrawText, you'll notice the difference.
TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding |
TextFormatFlags.VerticalCenter;
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var lv = sender as ListView;
var subItem = lv.HitTest(lv.PointToClient(MousePosition)).SubItem;
if (subItem != null && e.SubItem == subItem) {
using (var brush = new SolidBrush(SystemColors.Highlight)) {
e.Graphics.FillRectangle(brush, e.SubItem.Bounds);
}
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font,
e.Bounds, SystemColors.HighlightText, flags);
}
else {
e.DrawDefault = true;
}
}
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
=> e.DrawDefault = true;
// Invalidate on a mouse interaction, otherwise the ListView doesn't redraw the SubItem
private void listView1_MouseUp(object sender, MouseEventArgs e)
=> (sender as ListView).Invalidate();
Or, you can change the Colors of a SubItem when a mouse interaction is notified (here, using the MouseDown event) and save the previous state (just the Colors here). It's better to save the state because each SubItem can have it's own settings, so you cannot just revert back to the Parent ListViewItem or the ListView values.
As mentioned, set UseItemStyleForSubItems = false in each parent ListViewItem, otherwise the Colors settings are ignored.
Also, FullRowSelect must be set to false, otherwise it's pointless :)
Here, the state is saved in a nullable named Tuple Field, (ListViewSubItem, Color[]).
A class object is probably better, this is just shorter.
private (ListViewItem.ListViewSubItem Item, Color[] colors)? previousItem = null;
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
var lv = sender as ListView;
var subItem = lv.HitTest(e.Location).SubItem;
if (previousItem.HasValue) {
// If an Item's Colors have been changed, restore the state
// It removes the selection if you click in an empty area
previousItem.Value.Item.BackColor = previousItem.Value.colors[0];
previousItem.Value.Item.ForeColor = previousItem.Value.colors[1];
lv.Invalidate(previousItem.Value.Item.Bounds);
}
if (subItem != null) {
// Save the SubItem's colors state
previousItem = (subItem, new[] { subItem.BackColor, subItem.ForeColor });
// Set new Colors. Here, using the default highlight colors
subItem.BackColor = SystemColors.Highlight;
subItem.ForeColor = SystemColors.HighlightText;
lv.Invalidate(subItem.Bounds);
}
}
This is how this thing works:
▶ About the Item / SubItem index, as it's mentioned in the question:
When you retrieve the ListViewItem / SubItem clicked with ListView.HitTest
var hitTest = lv.HitTest(e.Location);
then the ListViewItem index is of course:
var itemIndex = hitTest.Item.Index;
and the SubItem.Index is:
var subItemIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);

How to get the selected SubItem index in a Listview and highlight it?

I am trying to get the selected ListViewItem index, so that when the user clicks on a particular row, such as row 2, I want the clicked cell's text to be set to a TextBox's text.
I also want to highlight only this cell, ideally using the regular selection ListView uses, or do I need to create a class that inherits from ListView to do this?
Something like this:
You can draw yourself the ListViewItem.ListViewSubItem selected, owner-drawing the Control (set ListView.OwnerDraw = true), then handle the ListView.DrawSubItem event.
The ListView.DrawColumnHeader event can use default values.
▶ I'm using TextRenderer since this is the default renderer. If you use Graphics.DrawText, you'll notice the difference.
TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding |
TextFormatFlags.VerticalCenter;
private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
var lv = sender as ListView;
var subItem = lv.HitTest(lv.PointToClient(MousePosition)).SubItem;
if (subItem != null && e.SubItem == subItem) {
using (var brush = new SolidBrush(SystemColors.Highlight)) {
e.Graphics.FillRectangle(brush, e.SubItem.Bounds);
}
TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.SubItem.Font,
e.Bounds, SystemColors.HighlightText, flags);
}
else {
e.DrawDefault = true;
}
}
private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
=> e.DrawDefault = true;
// Invalidate on a mouse interaction, otherwise the ListView doesn't redraw the SubItem
private void listView1_MouseUp(object sender, MouseEventArgs e)
=> (sender as ListView).Invalidate();
Or, you can change the Colors of a SubItem when a mouse interaction is notified (here, using the MouseDown event) and save the previous state (just the Colors here). It's better to save the state because each SubItem can have it's own settings, so you cannot just revert back to the Parent ListViewItem or the ListView values.
As mentioned, set UseItemStyleForSubItems = false in each parent ListViewItem, otherwise the Colors settings are ignored.
Also, FullRowSelect must be set to false, otherwise it's pointless :)
Here, the state is saved in a nullable named Tuple Field, (ListViewSubItem, Color[]).
A class object is probably better, this is just shorter.
private (ListViewItem.ListViewSubItem Item, Color[] colors)? previousItem = null;
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
var lv = sender as ListView;
var subItem = lv.HitTest(e.Location).SubItem;
if (previousItem.HasValue) {
// If an Item's Colors have been changed, restore the state
// It removes the selection if you click in an empty area
previousItem.Value.Item.BackColor = previousItem.Value.colors[0];
previousItem.Value.Item.ForeColor = previousItem.Value.colors[1];
lv.Invalidate(previousItem.Value.Item.Bounds);
}
if (subItem != null) {
// Save the SubItem's colors state
previousItem = (subItem, new[] { subItem.BackColor, subItem.ForeColor });
// Set new Colors. Here, using the default highlight colors
subItem.BackColor = SystemColors.Highlight;
subItem.ForeColor = SystemColors.HighlightText;
lv.Invalidate(subItem.Bounds);
}
}
This is how this thing works:
▶ About the Item / SubItem index, as it's mentioned in the question:
When you retrieve the ListViewItem / SubItem clicked with ListView.HitTest
var hitTest = lv.HitTest(e.Location);
then the ListViewItem index is of course:
var itemIndex = hitTest.Item.Index;
and the SubItem.Index is:
var subItemIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);

Change font style in gridcontrol devexpress?

how can i make italic font based on ISVERIFIKASI value?? if ISVERIFIKASI value is 1 make it all row font to italic and if it is 0 make it to default regular...
Any suggestion?
I suggest you use the GridView.RowStyle event.
using DevExpress.XtraGrid.Views.Grid;
//...
void gridView_RowStyle(object sender, RowStyleEventArgs e) {
GridView view = sender as GridView;
if(e.RowHandle >= 0) {
int value = (int)view.GetRowCellValue(e.RowHandle, view.Columns["ISVERIFIKASI"]);
if(value == 1)
e.Appearance.Font = ...;
}
}

Apply different properties on specific items in listbox

I fill a listbox listBoxHome from a dictionary dictionaryHome :
dictionaryHome.Add(item.Id, item.Name);
listBoxHome.DataSource = new BindingSource(dictionaryHome, null);
listBoxHome.DisplayMember = "Value";
listBoxHome.ValueMember = "Key";
I also use the following code to be able only first 5 items to be selectable
private void listBoxHome_SelectedIndexChanged(object sender, EventArgs e)
{
InvertMySelection(listBoxHome, listBoxAway);
//make only first5 selectable
for (int i = 5; i < listBoxHome.Items.Count; i++)
{
if (listBoxHome.GetSelected(i) == true)
listBoxHome.ClearSelected();
}
}
I want to apply a different color to the first 5 items and different color the other items.
Or maybe a transparent panel that shows difference from the first 5 items and the other items. Also I want to draw a line inside the listbox as shown in the image. Any suggestion?
EDIT:
Adding Luc Morin's code the result shown in the following picture
Is there a way to show only the text and not the id(as was before)?The id is used in the back.
First you need to set the DrawMode to OwnerDrawFixed in the Windows Forms Designer property grid.
Then, add an event handler to the ListBox.DrawItem event, something along those lines:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
// Draw the background of the ListBox control for each item.
e.DrawBackground();
// Define the default color of the brush as black.
Brush myBrush = Brushes.Black;
// Determine the color of the brush to draw each item based
// on the index of the item to draw.
if (e.Index < 3)
{
myBrush = Brushes.Red;
}
// Draw the current item text based on the current Font
// and the custom brush settings.
e.Graphics.DrawString(((KeyValuePair<int, string>)listBox1.Items[e.Index]).Value,
e.Font, myBrush, e.Bounds, StringFormat.GenericDefault);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
Adapt to your specific needs.
Code adapted from MSDN sample at: http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.drawitem(v=vs.110).aspx
Cheers
EDIT: In order to prevent selection of items, handle the ListBox.SelectedIhanged, something like this:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if(listBox1.SelectedIndex >=3)
{
listBox1.SelectedIndex = -1;
listBox1.Invalidate();
}
}
EDIT 2: When binding to a dictionary, the ListBox.Items collection actually contains KeyValuePair objects instead of just strings. I updated the code to account for this. My example assumes the Key is an int and the Value is a string.

How to make a non editable drop down combobox?

I am having the combobox of dropdownstyle - dropdownlist it is noneditable but in windows 7, its back color cannot be changed.so i want a non editable drop down down combobox .
There is two way to set the backcolor
First way
set the combobox property
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
then implement DrawItem event handler (sample code below)
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index > -1)
{
e.DrawBackground();
e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), this.Font, Brushes.Black, e.Bounds);
e.DrawFocusRectangle();
}
}
Second way
set the combobox property
comboBox1.FlatStyle = FlatStyle.Flat;
Then use the backcolor you needed for the combobox
stay on your comboBox and search the dropstyle property from properties window and then choose dropdown list;

Categories