winforms 表单:ComboBox:如何设置“空”值

epggiuax  于 2023-03-24  发布在  其他
关注(0)|答案(1)|浏览(305)

我有一个从标准ComboBox派生的类,在那里我将项目设置为DataSource

public sealed class TagComboBox : ComboBox
{
    public void SetItems(List<Tag> tags)
    {
        this.DisplayMember = nameof(TagComboBoxItem.Display);
        this.ValueMember = nameof(TagComboBoxItem.Value);

        this.DataSource = tags
            .Select(t => new TagComboBoxItem(t))
            .OrderBy(i => i.Display)
            .ToList();
    }

    private sealed class TagComboBoxItem
    {
        public string Display { get; }
        public Tag Value { get; }

        public TagComboBoxItem(Tag tag)
        {
            this.Display = tag?.Name ?? "(No Tag)";
            this.Value = tag;
        }
    }
}

在某些情况下,我在第一个位置插入一个“none”项:

tags.Insert(0, (Tag)null); //cast was a test but did not help
tagComboBox.SetItems(tags);

当为SelectedValue属性设置任何真实的标记时,它都能完美地工作。
在这种情况下,我可以简单地设置tagComboBox.SelectedIndex = 0;,因为我确切地知道“none”项在哪里,但我不明白为什么允许将ValueMember项添加为null,但不允许将其设置为SelectedValue

xmakbtuz

xmakbtuz1#

这是因为Windows窗体CurrencyManager的工作方式,它是在设置SelectedValue时用于定位项的管理器。
这是抛出您看到的异常的代码:

internal int Find(PropertyDescriptor property, Object key, bool keepIndex) {
    if (key == null)
        throw new ArgumentNullException("key");

    if (property != null && (list is IBindingList) && ((IBindingList)list).SupportsSearching) {
        return ((IBindingList)list).Find(property, key);
    }

    if (property != null) {
        for (int i = 0; i < list.Count; i++) {
            object value = property.GetValue(list[i]);
            if (key.Equals(value)) {
                return i;
            }
        }
    }

    return -1;
}

“Key”的值是您在SelectedValue中设置的值。
这将需要更多的调查,以了解为什么它已经实现了这种方式的原因,但我假设你只是想知道,如果你试图做什么可以做,从上面的代码,它不能。
也许你可以覆盖SelectedValue属性,如果传递的值为空,就在那里设置索引?
例如:

public new object SelectedValue
    {
        get => base.SelectedValue;
        set
        {
            if (value is null && _nullIndex >= 0) {
                SelectedIndex = _nullIndex;
                return;
            }
            base.SelectedValue = value;
        }
    }

在这种情况下,您需要将_nullIndex值存储在SetItems中。

_nullIndex = tags.IndexOf(tags.FirstOrDefault(t => t is null));

相关问题