C# - 将IEnumerable转换为Dictionary<object, string>

5

我正在构建一个WPF UserControl。为此,我实现了一个ItemSource DependecyProperty,如下所示:

private IEnumerable MisItems;
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(TextBoxAutoComplete), new PropertyMetadata(new PropertyChangedCallback(OnItemsSourcePropertyChanged)));

    private static void OnItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var control = sender as TextBoxAutoComplete;
        if (control != null)
            control.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
    }

    private void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
    {
        MisItems = newValue;
        // Remove handler for oldValue.CollectionChanged
        var oldValueINotifyCollectionChanged = oldValue as INotifyCollectionChanged;

        if (null != oldValueINotifyCollectionChanged)
        {
            oldValueINotifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
        }
        // Add handler for newValue.CollectionChanged (if possible)
        var newValueINotifyCollectionChanged = newValue as INotifyCollectionChanged;
        if (null != newValueINotifyCollectionChanged)
        {
            newValueINotifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
        }

    }

    void newValueINotifyCollectionChanged_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        //Do your stuff here.
    }

ItemsSource属性由一个IEnumerable对象表示。现在我需要在这个函数中将其转换为一个Dictionary<object,string>

protected SearchResult DoSearch(string searchTerm)
    {
        if (!string.IsNullOrEmpty(searchTerm))
        {
            SearchResult sr = new SearchResult();
            //var ItemsText = MisItems.GetType();
            var p = (List<string>)MisItems;

             /*sr.Results = ItemsText.Select((x, i) => new { x, i }).Where(x=>x.ToString().ToUpper().Contains(searchTerm.ToUpper()))
            .ToDictionary(a => (object)a.i, a => a.x);*/

            return sr;
        }
        else return new SearchResult();           
    }

我该如何进行转换?

编辑 更多信息: 我的视图模型具有以下属性:

public List<EnumeradorWCFModel> Clientes { get; set; }

这个属性的数据是由一个 WCF 服务返回的:
Clientes = _svc.Clientes_Enum(sTicket, "");

然后我希望我的UserControl可以绑定到这个属性。我像这样创建了我的控件:

<autocomplete:TextBoxAutoComplete x:Name="Clientes"  ItemsSource = "{Binding Path=Clientes}" DisplayMemberPath="Descripcion" Height="25"/>

你注释掉的代码有什么问题(除了你可能应该使用字符串比较而不是.ToUppers)? - Robert McKee
1
在注释掉的代码中,你难道不应该这样写吗:Where(x=>x.x.ToString()...?目前你正调用匿名类的 ToString 方法。 - juharr
好的,如果ItemsSource是一个简单的字符串数组,那么上面的注释行是有效的。但是当我将dataContext设置为一个复杂的行时,它不起作用,因为这一行var p = (List<string>)MisItems;当然会抛出异常。 - ericpap
请查看我的更新。 - ericpap
这可能不是一个好主意...你会使用一个object作为字典的键吗? - Dan Field
2个回答

12

[s]好的。你发布了很多代码(我个人认为对于你试图做的事情来说是不必要的)。

我们来简化一下吧。

你开始有一个 IEnumerable<string>,对吗?很好。

LINQ 库中有一个 ToDictionary() 扩展方法。文档在这里

所以你需要做的是:

IEnumerable<string> myEnumerableOfStrings = new List<string>();

Dictionary<object, string> dictionary = myEnumerableOfStrings.ToDictionary(value => (object) value);

这里有一个Fiddle作为示例。

好的,所以我们只有一个没有强类型的IEnumerable。(这是我第一次见或听说这样做,但相同的原则应该适用。)

我们需要创建一个本地字典并迭代该集合。

var myDictionary = new Dictionary<object, string>();
IEnumerable myCollection = new List<string>();

foreach(var item in myCollection)
{
    // This might be fun if you get two of the same object in the collection.
    // Since this key is based off of the results of the GetHashCode() object in the base object class.
    myDictionary.Add((object) item, item.ToString());
}

这里有一个例子。


感谢Cameron的帮助,如果代码太多就抱歉了。你的假设并不完全正确。我有一个像IEnumerable一样定义的dependenceProperty,而不是IEnumerable<string>,所以我没有.ToDictionary方法。请看我的更新。 - ericpap
@ericpap 所以你没有强类型?很酷。这会让问题变得稍微复杂一些,但并不是太糟糕。 - Cameron
谢谢!嗯,这似乎变得更加复杂了。您的代码可以工作,但字符串部分为空,所以我想item.ToString()返回null或空。我尝试使用myDictionary.Add((object)item, item.GetType().GetProperty("Descripcion").ToString()); 但结果相同。属性的名称应与DisplayMemberPath属性相关联。 - ericpap

1
上面的答案中,关于ToDictionary扩展方法的例子是一个原始类型(字符串)的列表,我想演示如何将复杂类型(类)的列表转换为字典。
这个重载方法是通过keySelector函数和elementSelector函数(docs)构建字典:
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);

例如:

public class FooClass 
{
    public int FooKey { get; set; }
    public string FooValue { get; set; }
}

IENumerable<FooClass> foos = new List<FooClass>();
IDictionary<int, string> dict = foos.ToDictionary<int, string>(x=>x.FooKey, x=>x.FooValue);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接