0
votes

I have created a listbox of expanders like this question: Expander Auto Open/Close

The solution works with content in the expanders when the listbox is the only item on the window.

But when I try to use the same code with my custom control, I'm getting this error:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ListBoxItem', AncestorLevel='1''. BindingExpression:Path=IsSelected; DataItem=null; target element is 'Expander' (Name=''); target property is 'IsExpanded' (type 'Boolean')

I've tried adding the IsSelected Property in the ListBox.ItemContainerStyle as one poster suggested in another thread but that failed.

<ListBox Margin="5"
         SelectionMode="Single"
         ScrollViewer.VerticalScrollBarVisibility="Auto">
    <ListBox.Resources>
        <Style TargetType="{x:Type Expander}">
             <Setter Property="IsExpanded"
                     Value="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
        </Style>
        <Style TargetType="{x:Type controls:SelectionCriteriaControl}">
             <Setter Property="MaxHeight"
                     Value="200" />
        </Style>
    </ListBox.Resources>
    <Expander Header="Fund Family" Margin="2">
        <StackPanel>
            <controls:SelectionCriteriaControl DataContext="{Binding FundFamilySelectionCriteria, Mode=TwoWay}" />
        </StackPanel>
    </Expander>
    <Expander Header="Asset Class" Margin="2">
        <StackPanel>
            <controls:SelectionCriteriaControl DataContext="{Binding AssetClassSelectionCriteria, Mode=TwoWay}" />
        </StackPanel>
    </Expander>
    <ListBox.Template>
        <ControlTemplate TargetType="{x:Type ListBox}">
            <ItemsPresenter />
        </ControlTemplate>
    </ListBox.Template>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ContentPresenter Content="{TemplateBinding Content}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Fails miserably!!!!!

Any help appreciated :)

1
How is it failing? What do you get on screen?XAMeLi
The expanders should be mutually exclusive, like grouped radiobuttons. If you click on one, and another is open, the 1st one should close. If you replace the UserControl embedded in the StackPanels with a TextBlock (for example), it works.Phil Boyd

1 Answers

2
votes

It's a bit of a large scenario for me to set up at the moment, but something that comes to mind to try:

Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected}" />

I don't think where templates are used that you can define relative sources by type.

Edit: This code worked fine: Based on your original, the TemplatedParent wasn't necessary.

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <ListBox x:Name="testList" Margin="5"
     SelectionMode="Single"
     ScrollViewer.VerticalScrollBarVisibility="Auto">
        <ListBox.Resources>
            <Style TargetType="{x:Type Expander}">
                <Setter Property="IsExpanded"
                 Value="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
            </Style>
        </ListBox.Resources>
        <Expander Header="Fund Family" Margin="2">
            <StackPanel>
                <TextBlock Text="First"/>
                <TextBlock Text="Second"/>
            </StackPanel>
        </Expander>
        <Expander Header="Asset Class" Margin="2">
            <StackPanel>
                <TextBlock Text="First"/>
                <TextBlock Text="Second"/>
            </StackPanel>
        </Expander>
        <ListBox.Template>
            <ControlTemplate TargetType="{x:Type ListBox}">
                <ItemsPresenter />
            </ControlTemplate>
        </ListBox.Template>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <ContentPresenter Content="{TemplateBinding Content}" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
    <Button HorizontalAlignment="Left" Content="Test" Grid.Row="1" Width="60" Click="Button_Click"/>
</Grid>

And a quick code-behind to trigger a programmatic SelectedIndex set...

        private void Button_Click(object sender, RoutedEventArgs e)
    {
        testList.SelectedIndex = 1;
    }

Seems to work fine for me. Clicking on a list item expands, and even using the button to set it specifically by setting the selected index it expands. Something very fishy is affecting your specific scenario... :]