简体   繁体   English

从 ObservableCollection 中的 Linq in ObservableCollection

[英]Linq in from ObservableCollection in ObservableCollection

I am tring to get the value "thisValueIwant".我试图获得值“thisValueIwant”。 Is there any possibility to get this value so easy?有没有可能这么容易地得到这个值? Or Maybe there is another solution for these 2 ObservableCollection或者也许这两个 ObservableCollection 有另一种解决方案

public class Foo
{
    public int number { get; set; }
    public ObservableCollection<FooInFoo> Details { get; set; }
}

public class FooInFoo
{
    public string thisValueIwant { get; set; }
}

public class TestClass
{
    public void Test()
    {
        ObservableCollection<Foo> FooCollection = new ObservableCollection<Foo>();

        FooCollection.Add(new Foo{
            number =1,
            Details = new ObservableCollection<FooInFoo>{ new FooInFoo {thisValueIwant = "very important string"}}
        });

        string x = (from f in FooCollection
                    where f.number == 1
                    select ???)
    }
}

Since ObservableCollection<FooInFoo> Details is a collection, you have to decide which details you want: the first, last, any or all.由于ObservableCollection<FooInFoo> Details是一个集合,你必须决定你想要的细节:第一个、最后一个、任何一个或全部。

Assuming you want the first:假设你想要第一个:

var d = FooCollection.Where(f => f.Number == 1).FirstOrDefault()?.Details.FirstOrDefault()?.thisValueIwant;

Or the last:或者最后一个:

var d = FooCollection.Where(f => f.Number == 1).FirstOrDefault()?.Details.LastOrDefault()?.thisValueIwant;

Or all (materialized as an array):或全部(具体化为数组):

var ds = FooCollection.Where(f => f.Number == 1).FirstOrDefault()?.Details.Select(d => d.thisValueIwant).ToArray();

An ObservableCollection<T> is a Collection<T> which implements IEnumerable<T> . ObservableCollection<T>是实现IEnumerable<T>Collection<T> IEnumerable<T> Therefore the fact that your FooCollection is an observable collection is not important, you can regard it as a sequence of Foo , an IEnumerable<Foo> and equally an IEnumerable<FooInFoo>因此,您的FooCollection是一个可观察集合这一事实并不重要,您可以将其视为FooIEnumerable<Foo>IEnumerable<FooInFoo>

Your code will be like (sorry, I only know how to write in Method format) In baby steps:您的代码将类似于(对不起,我只知道如何以 Method 格式编写)在婴儿步骤中:

IEnumerable<Foo> AllFooWithNumber1 = FooCollection
   .Where(foo => foo.Number == 1);

If you are certain there is exactly one continue with:如果您确定确实有一个继续:

Foo fooWithNumber1 = AllFooWithNumber1.Single();

Consider using SingleOrDefault if you are not certain that there is one.如果您不确定是否存在SingleOrDefault ,请考虑使用SingleOrDefault

Once you have the Foo that you want, you can select the Details:获得所需的 Foo 后,您可以选择详细信息:

IEnumerable<FooInFoo> detailsOfFooWithNumber1 = fooWithNumber1.Details;
FooInFoo detailIWant = detailsOfFooWithNumber1
   .Where(detail => some expression that uses detail...)
   .SingleOrDefault();

string thisValueIWant = defailtIWant.thisValueIWant;

Or in one statement:或者在一个声明中:

string thisValueIWant = FooCollection
   .Where(foo => foo.Number == 1)
   .Single()
   .Details
   .Where(detail => ...)
   .Single()
   .thisValueIWant;

Problems might arise if you are not certain there is one Single element.如果您不确定是否只有一个 Single 元素,则可能会出现问题。

If you want to check foo.Number for a given value AND all details for some predicate, consider using Enumerable.SelectMany .如果要检查给定值的 foo.Number 和某些谓词的所有详细信息,请考虑使用Enumerable.SelectMany This is used whenever you have sequences of sequences (arrays within arrays).只要您有序列序列(数组中的数组),就会使用它。 With SelectMany you enumerate over all these inner arrays as if it was one array:使用 SelectMany 您可以枚举所有这些内部数组,就好像它是一个数组一样:

IEnumerable<string> valuesIWant = FooCollection
    .Where(foo => foo.Number == 1)
    .SelectMany(foo => foo.Details)
    // now you have one sequence of all FooInFoo that are Details within
    // Foo objects with Number 1
    .Where(detail => expression that selects the FooInFoo you want)
    .Select(detail => detail.thisValueIWant);

You need my ObservableComputations library maybe.你可能需要我的ObservableComputations库。 Using this library you can code like this:使用这个库,你可以这样编码:

Expression<Func<string>> expr = () => 
   FooCollection
      .Filtering(а => f.number == 1)
      .FirstComputing().Value
      .Using(f => f != null 
           ? f.Details.FirstComputing().Using(fif => 
               fif.Value != null ? fif.Value.thisValueIwant : null).Value
           : null).Value;

Computing<string> x = expr.Computing();

// x.Value is what you want

x is INotifyPropertyChanged and notifies you about changes of computing result of expr. x 是INotifyPropertyChanged并通知您 expr 计算结果的变化。 Do not forget make all properties mentioned in the code above notify of changes through the INotifyPropertyChanged interface.不要忘记让上面代码中提到的所有属性通过INotifyPropertyChanged接口通知更改。

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

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