3

I've got a combobox that is bound to a List<Person> (ItemsSource is set in CodeBehind).

<ComboBox Width="120" Background="White" DisplayMemberPath="Name" />

So the names of all persons are added to the List.

Because it's not necessary to show every name in the ComboBox, I added a property Hide of type bool. If this property is set to true, the name should not be shown in the combobox.

But how is it possible to add a condition to the Binding of the combobox, so that only those persons are listed who are not supposed to be hidden.

EDIT: Regarding answers, I added the following code:

{
    List<Person> persons;
    ...
    var collectionView = CollectionViewSource.GetDefaultView(persons);
    collectionView.Filter = HideFilter;
}

...

private bool HideFilter(object item)
{
   Person p = item as Person;
   return p.Hide;
}

But this throws a TargetInvocationException on collectionView.Filter = HideFilter;.
What did I misunderstand?

Em1
  • 1,077
  • 18
  • 38

4 Answers4

5

You could either filter in the code behind, or you could use a item template to bind visibility of the Item to the isHiden property (with a boolean to visilbility converter). Your XAML code would be:

     <ComboBox Grid.Column="1" Grid.Row="0" >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Visibility="{Binding IsVisible}" Text="{Binding Name}"/>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>


public class person
{
    public person(string n, Visibility v)
    {
        Name = n;
        IsVisible = v;
    }
    public string Name {get;set;}
    public Visibility IsVisible { get; set; }
}
seekle
  • 228
  • 2
  • 7
  • This is a really interesting solution. I've tried it, but it does not work, although the getter runs, and the debugger shows me 'false'. I've to investigate, whats really happens in this case. – Em1 Jun 22 '11 at 14:50
  • 1
    The class has to implement `INotifyPropertyChanged` and raise `PropertyChanged` when the `IsVisible` property changes. – Robert Rossney Jun 22 '11 at 15:02
  • ..and set `UpdateSourceTrigger=PropertyChanged` on the Visibility binding – DefenestrationDay Jan 23 '14 at 17:35
  • @Em1 - _debugger shows me false_. Don't forget though that whilst your object can return a **bool**, the **Visibility** property is of type _Visibility_ not **bool**. You may need a **IValueConverter** –  Feb 17 '14 at 06:01
2

You need to add a filter to the CollectionViewSource of the data source, your list, you can get this collection with the static method CollectionViewSource.GetDefaultView(list)

you'll get a nice interface where you can add a filter that says (hide = false)

Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141
0

My suggestions is to not do it this way. Why? It is not wrong, but it produces empty collapsed rows in the combobox! :/
In my case I had a list of five users and deleted all. But I had still five tiny little clickable(!) rows inside of the combobox. oO

<ComboBox Grid.Column="1" Grid.Row="0" >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Visibility="{Binding IsVisible}" Text="{Binding Name}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Instead I use code like shown below. It's my solution for a user list. When I mark a user as deleted (if selected, click on button, mark as deleted), it disappears from the list completely.

<ComboBox ItemsSource="{Binding Path=UserList}"
        SelectedItem="{Binding SelectedUser}"
        DisplayMemberPath="Name"
        IsEnabled="{Binding SelectedUser.HasErrors, TargetNullValue=True, FallbackValue=True, ValidatesOnNotifyDataErrors=False, Converter={StaticResource Bool2BoolNot}}"
        IsEditable="False"
        >
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Deleted}" Value="True">
                    <DataTrigger.Setters>
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger.Setters>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=Special}" Value="True">
                    <DataTrigger.Setters>
                        <Setter Property="Foreground" Value="Red"/>
                    </DataTrigger.Setters>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=Super}" Value="True">
                    <DataTrigger.Setters>
                        <Setter Property="Foreground" Value="DarkRed"/>
                    </DataTrigger.Setters>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>
Em1
  • 1,077
  • 18
  • 38
René Hankel
  • 53
  • 2
  • 6
0

you can apply linq query on the List before making it a source

List<Person> persons = new List<Person> ();
var Filter =  from p in persons
           where p.hide == false
           select p;

Now renew persons and provide Filter as a list to it cast this Filter into List and defined it combo source...

persons  = new List<Person>(Filter);
cbm.ItemSource = persons  ;
Syeda
  • 1,215
  • 11
  • 23