Right justified combobox in C#
Asked Answered
K

4

8

By default the items in the C# Combobox are left aligned. Are there any options available to change this justification apart from overriding DrawItem method and setting the combobox drawmode --> DrawMode.OwnerDrawFixed?

Cheers

Kneecap answered 23/6, 2010 at 5:29 Comment(1)
I added winforms tag to your question since I assume from the fact you mentioned DrawItem that you're not referring to WPF. This doesn't really have anything to do with C# though, but I didn't want to remove a tag.Nunhood
A
4

You could just set the control style to RightToLeft = RightToLeft.Yes if you don't mind the drop widget on the other side as well.

or

set DrawMode = OwnerDrawFixed; and hook the DrawItem event, then something like

    private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        if (e.Index == -1)
            return;
        ComboBox combo = ((ComboBox) sender);
        using (SolidBrush brush = new SolidBrush(e.ForeColor))
        {
            e.DrawBackground();
            e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font, brush, e.Bounds, new StringFormat(StringFormatFlags.DirectionRightToLeft));
            e.DrawFocusRectangle();
        }
    }
Acupuncture answered 23/6, 2010 at 6:26 Comment(2)
Hi ... There is no difference i can see even after i implemented this handler.Kneecap
not sure why, did you remember to set the property of the combo box DrawMode to OwnerDrawFixed. And do you have some items in the list.Acupuncture
N
2

In WPF this would be as easy as specifying an ItemContainerStyle. In Windows Forms it's a little trickier. Without custom drawing, you could set the RightToLeft property on the ComboBox but this would unfortunately also affect the drop down button.

Since Windows Forms uses a native ComboBox, and Windows doesn't have a ComboBox style like ES_RIGHT that affects the text alignment, I think your only option is to resort to owner draw. It would probably be a good idea to derive a class from ComboBox and add a TextAlignment property or something. Then you would only apply your drawing if TextAlignment was centered or right aligned.

Nunhood answered 23/6, 2010 at 6:3 Comment(3)
Hi ... In this case how do i apply the TextAlignment to the control? Are you hinting at the string format here ?Kneecap
No I'm saying you would need to create a control that derives from ComboBox and add a new property called TextAlignment. Then in your OnDrawItem method you can take this property into account, rather than hard coding an alignment.Nunhood
Example: msdn.microsoft.com/en-us/library/…Nunhood
E
1

You must "DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed" and your own draw method like this.

protected virtual void OnDrawItem(object sender, DrawItemEventArgs e)
{
    var comboBox = sender as ComboBox;

    if (comboBox == null)
    {
        return;
    }

    e.DrawBackground();

    if (e.Index >= 0)
    {
        StringFormat sf = new StringFormat();
        sf.LineAlignment = StringAlignment.Center;
        sf.Alignment = StringAlignment.Center;

        Brush brush = new SolidBrush(comboBox.ForeColor);

        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
            brush = SystemBrushes.HighlightText;
        }

        e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, brush, e.Bounds, sf);
    }
}
Ennoble answered 4/7, 2015 at 5:54 Comment(0)
D
0

Unfortunately the approach with OwnDrawItem seems not to work if the combo box is set to DropDownList.Then one sees a white background instead of the expected gray. So I came with using a WPF combo box, with also does not look exactly as the "normal" combo box but is close enough.

For me it was sufficient to implement two properties, one method and one vent as follows:

    public partial class RightAlignedComboBox : ElementHost {

    public RightAlignedComboBox() {                   
        InitializeComponent();

        _comboBox = new() {
            HorizontalAlignment = HorizontalAlignment.Stretch,
            VerticalAlignment = VerticalAlignment.Stretch,
            HorizontalContentAlignment = HorizontalAlignment.Right,
            VerticalContentAlignment = VerticalAlignment.Center
        };

        _comboBox.SelectionChanged += comboBox_SelectionChanged;
        _comboBox.MouseWheel += comboBox_MouseWheel;

        this.Child = _comboBox;
    }

    #region Properties & Variables

    private ComboBox _comboBox;

    private IEnumerable<object> _items;

    /// <summary>
    /// Gets or sets the index specifying the currently selected item.
    /// </summary>      
    public int SelectedIndex {
        get {
            return _comboBox.SelectedIndex;
        }
        set {
            _comboBox.SelectedIndex = value;
        }
    }

    /// <summary>
    /// Gets or sets currently selected item in the combo box.
    /// </summary>      
    public object SelectedItem {
        get {
            return _items.ElementAt(_comboBox.SelectedIndex);
        }
        set {
            int selectedIndex = _items.IndexOfFirst(item => item.ToString() == value.ToString());
            _comboBox.SelectedIndex = selectedIndex;
        }
    }

    #endregion

    #region Methods

    /// <summary>
    /// Sets the items selectable in the combo box.
    /// </summary>
    /// <param name="items">The items to be put in the combo box.</param>
    public void SetItems(IEnumerable<object> items) {
        _items = items;

        _comboBox.Items.Clear();

        for (int i = 0; i < items.Count(); i++) {
            _comboBox.Items.Add(new ComboBoxItem() { Content = items.ElementAt(i).ToString() });
        }
    }

    #endregion

    #region Own events

    /// <summary>
    /// Event that is raised when the <see cref="SelectedIndex"/> changed either by clicking or by mouse wheel.
    /// </summary>
    public event EventHandler SelectionChangeCommitted = null;

    /// <summary>
    /// Raises the <see cref="SelectionChangeCommitted"/> event.
    /// </summary>
    private void onSelectionChangeCommitted() {
        SelectionChangeCommitted?.Invoke(this, EventArgs.Empty);
    }

    #endregion

    #region Events

    private void comboBox_MouseWheel(object sender, MouseWheelEventArgs e) {
        if (e.Delta < 0) {
            if (_comboBox.SelectedIndex != _comboBox.Items.Count - 1) {
                _comboBox.SelectedIndex++;
                onSelectionChangeCommitted();
            }
        }
        else {
            if (_comboBox.SelectedIndex != 0) {
                _comboBox.SelectedIndex--;
                onSelectionChangeCommitted();
            }
        }
    }

    private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
        if (_comboBox.IsFocused) {
            onSelectionChangeCommitted();
        }
    }

    #endregion
}
Dansby answered 21/9, 2023 at 10:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.