简体   繁体   中英

Linq in from ObservableCollection in ObservableCollection

I am tring to get the value "thisValueIwant". Is there any possibility to get this value so easy? Or Maybe there is another solution for these 2 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.

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> . 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>

Your code will be like (sorry, I only know how to write in Method format) In baby steps:

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.

Once you have the Foo that you want, you can select the Details:

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.

If you want to check foo.Number for a given value AND all details for some predicate, consider using 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:

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. 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. Do not forget make all properties mentioned in the code above notify of changes through the INotifyPropertyChanged interface.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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