繁体   English   中英

Combobox 如何设置 selectedValue

[英]Combobox how to set selectedValue

我有一个 combobox 我在里面填充字体。 我用来这样做的方法在这个链接中。 我将在这里分享该问题的答案。

public YourForm()
{
    InitializeComponent();

    ComboBoxFonts.DrawItem += ComboBoxFonts_DrawItem;           
    ComboBoxFonts.DataSource = System.Drawing.FontFamily.Families.ToList();
}

private void ComboBoxFonts_DrawItem(object sender, DrawItemEventArgs e)
{
    var comboBox = (ComboBox)sender;
    var fontFamily = (FontFamily)comboBox.Items[e.Index];
    var font = new Font(fontFamily, comboBox.Font.SizeInPoints);

    e.DrawBackground();
    e.Graphics.DrawString(font.Name, font, Brushes.Black, e.Bounds.X, e.Bounds.Y);
}

现在我只对此代码进行了 1 处更改,就是这样:

cmbFonts.DrawMode = DrawMode.OwnerDrawFixed;

加载 fonts 没有问题,它正在工作,但我尝试在我的表单加载时设置 selectedvalue。 例如,我尝试设置名为“arial”的字体。 为了做到这一点,我使用这个:

var dataSource = cmbFonts.DataSource as List<FontFamily>;
int res = -1;
try
{
  res = dataSource.IndexOf(new FontFamily(StaticVariables.FontName));
}
catch { }
if (res != -1)
  cmbFonts.SelectedIndex = res;

现在,当我这样做时,我得到System.ArgumentOutOfRangeException错误,因为我没有向Combobox添加任何项目我绑定了一个DataSource ,因此当我尝试设置SelectedIndex时,我得到了这个错误,我知道,我也试过这个:

cmbFonts.SelectedValue = StaticVariables.FontName;

但是当我在 Visual Studio 中运行带有断点的代码时,我发现我的SelectedValue永远不会改变。 在执行该行之前,我看到 null 并且在执行之后我仍然在SelectedValue中看到 null ,我检查了我的 StaticVariables.FontName 变量,字体显示在其中。

我也尝试过使用combobox.Text属性,但没有运气,就像SelectedValue一样,之前是空字符串,在我用断点跳过它之后仍然相同。

TL;DR:我尝试在 combobox 中填写 select 表单加载项,其中我填充了DataSource

Here's a custom owner-drawn ComboBox class (here, named FontListCombo ) that shows compatible System Font Families, representing each ComboBox Item using the FontFamily name as the Item Text and the corresponding Font to draw the Item's text (a classic ComboBox Font selector, in实践)。

自定义控件在运行时自动填充系统中可用的 Fonts 列表。 它还响应WM_FONTCHANGE消息(系统字体池更改时广播;例如,在Fonts文件夹中添加或删除字体),以更新字体列表并反映更改(也避免尝试使用已经不存在了)。

ComboBox 项目的文本是使用TextRenderer.DrawText()而不是Graphics.DrawString()绘制的,因为前者在这种情况下会产生更清晰的结果。

The ComboBox.Items collection is represented by a collection of FontObject class objects, a public class that stores some of the properties of each FontFamily and also exposes a couple of static methods used internally to return a Font object or a FontFamily object, calling the corresponding自定义 ComboBox 的公共方法:

  • GetSelectedFont(SizeInPoints, FontStyle)方法从当前ComboBox.SelectedItem
  • GetSelectedFontFamily()从当前ComboBox.SelectedItem

它还覆盖ToString() ,以返回其属性值的摘要。

这种 object 容器更适合这里:将 FontFamily object 存储为 ConboBox 项肯定会产生不同类型的问题,最明显和最可悲的是,某些 FontFamily 对象会随着时间的推移甚至在它们被删除后立即失效存储。 这些对象一开始并不意味着永久存储,所以这并不奇怪。

如示例所示,从ComboBox.SelecteItem中获取当前的 Font 和 FontFamily :
(这里, ComboBox 实例被命名为cboFontList

private void cboFontList_SelectionChangeCommitted(object sender, EventArgs e)
{
    Font font = cboFontList.GetSelectedFont(this.Font.SizeInPoints, FontStyle.Regular);
    FontFamily family = cboFontList.GetSelectedFontFamily();
    string fontDetails = (cboFontList.SelectedItem as FontListCombo.FontObject).ToString();
}

FontObject class 存储了 FontFamily 的一些重要细节,例如Cell AscentCell DescentEM SizeLine Spacing
此处描述了有关如何使用这些功能的一些详细信息:

使用图形路径正确绘制文本
Fonts 和文本指标

这是它的工作原理:

自定义组合框字体选择器


FontListCombo 自定义控件:

using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

[DesignerCategory("Code")]
public class FontListCombo : ComboBox
{
    private List<FontObject> fontList = null;

    public FontListCombo() {
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.DrawMode = DrawMode.OwnerDrawVariable;
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        if (!DesignMode) GetFontFamilies();
    }

    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        if ((Items.Count == 0) || e.Index < 0) return;
        e.DrawBackground();
        var flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
        using (var family = new FontFamily(this.GetItemText(Items[e.Index])))
        using (var font = new Font(family, 10F, FontStyle.Regular, GraphicsUnit.Point)) {
            TextRenderer.DrawText(e.Graphics, family.Name, font, e.Bounds, this.ForeColor, flags);
        }
        e.DrawFocusRectangle();
        base.OnDrawItem(e);
    }

    protected override void OnMeasureItem(MeasureItemEventArgs e) {
        base.OnMeasureItem(e);
        e.ItemHeight = this.Font.Height + 4;
    }

    private void GetFontFamilies()
    {
        this.fontList = new List<FontObject>();

        fontList.AddRange(FontFamily.Families
            .Where(f => f.IsStyleAvailable(FontStyle.Regular))
            .Select(f => new FontObject(f)).ToArray());
        this.DisplayMember = "FamilyName";
        this.ValueMember = "EmHeight";
        this.DataSource = fontList;
    }

    public FontFamily GetSelectedFontFamily()
    {
        if (this.SelectedIndex < 0) return null;
        return FontObject.GetSelectedFontFamily((FontObject)this.SelectedItem);
    }

    public Font GetSelectedFont(float sizeInPoints, FontStyle style)
    {
        if (this.SelectedIndex < 0) return null;
        return FontObject.GetSelectedFont((FontObject)this.SelectedItem, sizeInPoints, style);
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg) {
            case WM_FONTCHANGE:  // The System Font pool has changed
                GetFontFamilies();
                break;
        }
    }

    public class FontObject
    {
        public FontObject(FontFamily family) { GetFontFamilyInfo(family); }
        public string FamilyName { get; set; }
        public int EmHeight { get; set; }
        public int CellAscent { get; set; }
        public int CellDescent { get; set; }
        public int LineSpacing { get; set; }

        private void GetFontFamilyInfo(FontFamily family)
        {
            this.FamilyName = family.Name;
            this.EmHeight = family.GetEmHeight(FontStyle.Regular);
            this.CellAscent = family.GetCellAscent(FontStyle.Regular);
            this.CellDescent = family.GetCellDescent(FontStyle.Regular);
            this.LineSpacing = family.GetLineSpacing(FontStyle.Regular);
        }
        internal static FontFamily GetSelectedFontFamily(FontObject fobj) 
            => new FontFamily(fobj.FamilyName);

        internal static Font GetSelectedFont(FontObject fobj, float sizeInPoints, FontStyle style) 
            => new Font(GetSelectedFontFamily(fobj), sizeInPoints, style);

        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.AppendLine(this.FamilyName);
            sb.AppendLine($"Em Height: {this.EmHeight}");
            sb.AppendLine($"Cell Ascent: {this.CellAscent}");
            sb.AppendLine($"Cell Descent: {this.CellDescent}");
            sb.AppendLine($"Line Spacing: {this.LineSpacing}");
            return sb.ToString();
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM