使用 "generic value" 将对象转换为 KeyValuePair?
Cast object to KeyValuePair with "generic value"?
我有一个组合框,里面装满了两种不同类型的混合项目。类型是
KeyValuePair<Int32, FontFamily>
或
KeyValuePair<Int32, String>
现在有些场合我只对所选项目的Key感兴趣,它总是一个Int32。
访问所选项目的密钥的最简单方法是什么?我在想
Int32 key = ((KeyValuepair<Int32, object/T/var/IdontCare>)combobox.SelectedItem).Key;
但这不起作用。
所以我只有
Int32 key;
if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, FontFamily)))
{
key = ((KeyValuePair<Int32, FontFamily)combobox.SelectedItem).Key;
}
else if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, String)))
{
key = ((KeyValuePair<Int32, String)combobox.SelectedItem).Key;
}
哪个可行,但我想知道是否有更优雅的方法?
你当然不需要使用GetType()
。您可以使用:
int key;
var item = combobox.SelectedItem;
if (item is KeyValuePair<int, FontFamily>)
{
key = ((KeyValuePair<int, FontFamily>) item).Key;
}
else if (item is KeyValuePair<int, string>)
{
key = ((KeyValuePair<int, string>) item).Key;
}
我认为不使用反射或动态类型真的没有更好的方法,假设您不能将所选项目的类型更改为您自己的等同于 KeyValuePair
的某些非通用基础类型或接口。
您可以像这样创建自己的 class 层次结构
public interface IComboBoxItem
{
public int Key { get; }
}
public class ComboBoxItem<T> : IComboBoxItem
{
public T Value { get; set; }
public int Key { get; set; }
}
您的演员阵容将如下所示:
key = ((IComboBoxItem)combobox.SelectedItem).Key;
我猜它绑定在 WPF 中,在那种情况下我建议不要使用 KeyValuePair<TKey,TValue>
,而是使用自己的 VM class。例如
class MyComboItem
{
private String _stringValue;
private FontFamiliy _fontFamilyValue;
public Int32 Key {get;set;}
public object Value => (_fontFamilyValue!=null)?_fontFamilyValue:_stringValue;
}
或者你可以有一个像
这样的界面
interface IMyComboItem
{
Int32 Key {get;}
object Value {get;}
}
并实现两个 VM classes 来实现它存储正确的值类型。
使用适当的构造函数等。使用泛型无法实现随心所欲的转换,并且您的解决方案也不优雅。
投射到 dynamic
(可怜人的反思)可以做到这一点
var key = (int) ((dynamic) comboxbox.SelectedItem).Key);
基于 Rich 的回答,我成功地使用了 Dynamic。我知道我要绑定的字典类型(实际上可以使用字典本身,因为它仍然在我的表单中引用),但我想创建一种方法来按显示名称进行搜索。这最终会检查绑定源是否也是数据表,但目前,这对 字典很有效。
private void SetComboBoxSelection(ComboBox cmb, string ItemText)
{
if (cmb.DisplayMember.ToLower() == "key" && cmb.ValueMember.ToLower() == "value")
{
foreach (dynamic item in cmb.Items)
if (item.Key == ItemText)
cmb.SelectedItem = item.Value;
}
}
我有一个组合框,里面装满了两种不同类型的混合项目。类型是
KeyValuePair<Int32, FontFamily>
或
KeyValuePair<Int32, String>
现在有些场合我只对所选项目的Key感兴趣,它总是一个Int32。
访问所选项目的密钥的最简单方法是什么?我在想
Int32 key = ((KeyValuepair<Int32, object/T/var/IdontCare>)combobox.SelectedItem).Key;
但这不起作用。
所以我只有
Int32 key;
if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, FontFamily)))
{
key = ((KeyValuePair<Int32, FontFamily)combobox.SelectedItem).Key;
}
else if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, String)))
{
key = ((KeyValuePair<Int32, String)combobox.SelectedItem).Key;
}
哪个可行,但我想知道是否有更优雅的方法?
你当然不需要使用GetType()
。您可以使用:
int key;
var item = combobox.SelectedItem;
if (item is KeyValuePair<int, FontFamily>)
{
key = ((KeyValuePair<int, FontFamily>) item).Key;
}
else if (item is KeyValuePair<int, string>)
{
key = ((KeyValuePair<int, string>) item).Key;
}
我认为不使用反射或动态类型真的没有更好的方法,假设您不能将所选项目的类型更改为您自己的等同于 KeyValuePair
的某些非通用基础类型或接口。
您可以像这样创建自己的 class 层次结构
public interface IComboBoxItem
{
public int Key { get; }
}
public class ComboBoxItem<T> : IComboBoxItem
{
public T Value { get; set; }
public int Key { get; set; }
}
您的演员阵容将如下所示:
key = ((IComboBoxItem)combobox.SelectedItem).Key;
我猜它绑定在 WPF 中,在那种情况下我建议不要使用 KeyValuePair<TKey,TValue>
,而是使用自己的 VM class。例如
class MyComboItem
{
private String _stringValue;
private FontFamiliy _fontFamilyValue;
public Int32 Key {get;set;}
public object Value => (_fontFamilyValue!=null)?_fontFamilyValue:_stringValue;
}
或者你可以有一个像
这样的界面interface IMyComboItem
{
Int32 Key {get;}
object Value {get;}
}
并实现两个 VM classes 来实现它存储正确的值类型。 使用适当的构造函数等。使用泛型无法实现随心所欲的转换,并且您的解决方案也不优雅。
投射到 dynamic
(可怜人的反思)可以做到这一点
var key = (int) ((dynamic) comboxbox.SelectedItem).Key);
基于 Rich 的回答,我成功地使用了 Dynamic。我知道我要绑定的字典类型(实际上可以使用字典本身,因为它仍然在我的表单中引用),但我想创建一种方法来按显示名称进行搜索。这最终会检查绑定源是否也是数据表,但目前,这对
private void SetComboBoxSelection(ComboBox cmb, string ItemText)
{
if (cmb.DisplayMember.ToLower() == "key" && cmb.ValueMember.ToLower() == "value")
{
foreach (dynamic item in cmb.Items)
if (item.Key == ItemText)
cmb.SelectedItem = item.Value;
}
}