Joseph Little
Joseph Little

Reputation: 931

Perform a Select on an ObservableCollection

In the same way I can filter items from my ObservableCollection using the Filter property on the collection's ICollectionView, is it possible to perform a Select on the collection too (In the same way I can with Linq)?

For an example, imagine I have a list of Food objects which doesn't have a Selected property, but I maintain which foods are selected in a separate list. Ideally I would want to perform my Select like so:

view.Select(f => return new { Food = f, Selected = selectedFood.Contains(f)});

I could then bind to the items returned from this Select like so:

<ListBox ItemsSource="{Binding FoodView}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <CheckBox IsChecked="{Binding Selected}">
            <TextBlock Text="{Binding Food.Name}"/>
        </CheckBox>
    </DataTemplate>
</ListBox.ItemTemplate>

I'm currently achieving the result I want by maintaining separate ObservableCollections and updating them as needed, but I was wondering if there was a more elegant solution.

Cheers!

Upvotes: 2

Views: 2203

Answers (1)

Jack
Jack

Reputation: 1006

I'm not sure if this is what you're looking for but I created an IMultiValueConverter which takes two bindings, the first being the current Data Object and the second being the list of Selected Items:

<ListBox ItemsSource="{Binding FoodItems}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">

                <CheckBox>
                    <CheckBox.IsChecked>
                        <MultiBinding Converter="{StaticResource ListExistsConverter}" Mode="OneWay">
                            <Binding/>
                            <Binding Path="DataContext.SelectedFoodItems" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
                        </MultiBinding>
                    </CheckBox.IsChecked>
                </CheckBox>

                <TextBox Text="{Binding Name}" Width="50" Height="20"/>

            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Converter:

class ListExistsConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null) return null;
        var item = values[0] as Food;
        var list = values[1] as List<Food>;

        return list.Contains(item);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

enter image description here enter image description here

The resources used consist of an ObservableCollection<Food> FoodItems and a List<Food> SelectedFoodItems. Perhaps not the most elegant but should be easy to switch between SelectedItem lists as needed.

Upvotes: 1

Related Questions