简体   繁体   English

Combobox 如何设置 selectedValue

[英]Combobox how to set selectedValue

I have a combobox which I fill font's inside.我有一个 combobox 我在里面填充字体。 The method I use to do so is in this link.我用来这样做的方法在这个链接中。 I will share the answer from that question here.我将在这里分享该问题的答案。

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

now I have only made 1 change to this code and that's this:现在我只对此代码进行了 1 处更改,就是这样:

cmbFonts.DrawMode = DrawMode.OwnerDrawFixed;

there is no problem with loading fonts and it's working but I try to set the selectedvalue on my form load.加载 fonts 没有问题,它正在工作,但我尝试在我的表单加载时设置 selectedvalue。 For example I try to set font named "arial".例如,我尝试设置名为“arial”的字体。 In order to do so I use this:为了做到这一点,我使用这个:

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;

now when I do this I get System.ArgumentOutOfRangeException error because I did not add any Items to Combobox I bind a DataSource therefore when I try to set SelectedIndex I get this error and I know that, I also tried this:现在,当我这样做时,我得到System.ArgumentOutOfRangeException错误,因为我没有向Combobox添加任何项目我绑定了一个DataSource ,因此当我尝试设置SelectedIndex时,我得到了这个错误,我知道,我也试过这个:

cmbFonts.SelectedValue = StaticVariables.FontName;

but when I run my code with breakpoints in Visual studio I see that my SelectedValue never changes.但是当我在 Visual Studio 中运行带有断点的代码时,我发现我的SelectedValue永远不会改变。 Before the line is executed I see null and after the execution I still see null in SelectedValue , I checked my StaticVariables.FontName variable and the font is presented in there.在执行该行之前,我看到 null 并且在执行之后我仍然在SelectedValue中看到 null ,我检查了我的 StaticVariables.FontName 变量,字体显示在其中。

I've also tried to use combobox.Text property but no luck, it's like SelectedValue , was empty string before and still same after I skip it with breakpoint.我也尝试过使用combobox.Text属性,但没有运气,就像SelectedValue一样,之前是空字符串,在我用断点跳过它之后仍然相同。

TL;DR: I try to select an item on form load in combobox which I filled with DataSource 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 practice). 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实践)。

The Custom Control automatically fills itself, at run-time, with the list of available Fonts in the System.自定义控件在运行时自动填充系统中可用的 Fonts 列表。 It also react to WM_FONTCHANGE messages (broadcast when the System Font pool changes; eg, a Font is added to or removed from the Fonts folder), to updated the Font list and reflect the change (to also avoid to try and use a Font that doesn't exist anymore).它还响应WM_FONTCHANGE消息(系统字体池更改时广播;例如,在Fonts文件夹中添加或删除字体),以更新字体列表并反映更改(也避免尝试使用已经不存在了)。

The text of the ComboBox Items is drawn using TextRenderer.DrawText() instead of Graphics.DrawString() , since the former grants sharper results in this context. 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 public methods of the custom ComboBox: 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 的公共方法:

  • The GetSelectedFont(SizeInPoints, FontStyle) method return a Font object from the current ComboBox.SelectedItem . GetSelectedFont(SizeInPoints, FontStyle)方法从当前ComboBox.SelectedItem
  • GetSelectedFontFamily() return the FontFamily object from the current ComboBox.SelectedItem . GetSelectedFontFamily()从当前ComboBox.SelectedItem

It also overrides ToString() , to return a summary of values of its properties.它还覆盖ToString() ,以返回其属性值的摘要。

This kind of object container is a better fit here: storing FontFamily object as the ConboBox Items would, most surely, create different sorts of problems, the most visible and tragic is that some FontFamily objects become invalid over time or even right after they have been stored.这种 object 容器更适合这里:将 FontFamily object 存储为 ConboBox 项肯定会产生不同类型的问题,最明显和最可悲的是,某些 FontFamily 对象会随着时间的推移甚至在它们被删除后立即失效存储。 These objects are not meant to be stored permanently to begin with, so it's not exactly a surprise.这些对象一开始并不意味着永久存储,所以这并不奇怪。

As shown in the example, to get the current Font and FontFamily from the ComboBox.SelecteItem :如示例所示,从ComboBox.SelecteItem中获取当前的 Font 和 FontFamily :
(here, the ComboBox instance is named cboFontList ) (这里, 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();
}

The FontObject class stores some important details of the FontFamily, such as the Cell Ascent , the Cell Descent , the EM Size and the Line Spacing . FontObject class 存储了 FontFamily 的一些重要细节,例如Cell AscentCell DescentEM SizeLine Spacing
Some details on how to use these features are described here:此处描述了有关如何使用这些功能的一些详细信息:

Properly draw text using Graphics Path使用图形路径正确绘制文本
Fonts and text metrics Fonts 和文本指标

This is how it works:这是它的工作原理:

自定义组合框字体选择器


FontListCombo Custom Control: 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