C# 中的右对齐组合框

发布于 2024-09-06 13:02:18 字数 115 浏览 5 评论 0原文

默认情况下,C# 组合框中的项目左对齐。 除了重写 DrawItem 方法和设置组合框绘制模式之外,是否有任何选项可用于更改此理由 --> DrawMode.OwnerDrawFixed?

干杯

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初心未许 2024-09-13 13:02:18

如果您不介意另一侧的放置小部件,则可以将控件样式设置为 RightToLeft = RightToLeft.Yes

设置 DrawMode = OwnerDrawFixed; 并挂钩 DrawItem 事件,
然后像

    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();
        }
    }

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();
        }
    }
幼儿园老大 2024-09-13 13:02:18

在 WPF 中,这就像指定 ItemContainerStyle 一样简单。在 Windows 窗体中,这有点棘手。如果没有自定义绘图,您可以在 ComboBox 上设置 RightToLeft 属性,但不幸的是,这也会影响下拉按钮。

由于 Windows 窗体使用本机 ComboBox,并且 Windows 没有类似 的 ComboBox 样式ES_RIGHT 会影响文本对齐,我认为您唯一的选择是诉诸所有者绘制。从 ComboBox 派生一个类并添加 TextAlignment 属性或其他内容可能是个好主意。然后,只有当 TextAlignment 居中或右对齐时,您才会应用绘图。

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.

孤者何惧 2024-09-13 13:02:18

您必须“DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed”并且
你自己的绘制方法是这样的。

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);
    }
}

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);
    }
}
半步萧音过轻尘 2024-09-13 13:02:18

不幸的是,如果组合框设置为 DropDownList,则 OwnDrawItem 的方法似乎不起作用。然后人们会看到白色背景而不是预期的灰色。因此,我使用了 WPF 组合框,它看起来也与“正常”组合框不完全相同,但足够接近。

对我来说,实现两个属性、一种方法和一个通风口就足够了,如下所示:

    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
}

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文