tags:

views:

177

answers:

1

I have a window with two listboxes both bound to an XMLDataProvider. The SelectedItem property of Listbox1 is two-way-bound to the SelectedItem property of ListBox2. So far so good.

ListBox2 contains a Styletrigger which sets IsSelected to true when the mouse hovers over an item. The corresponding item in ListBox1 is selected too because of the two-way binding. The problem arises when I select an item in Listbox1 by clicking on it. For example when I select "Book 1" in ListBox1 then move the mouse over all items in ListBox2 the item "Book 1" will no longer be selected when the style trigger fires. As soon as I select an item in Listbox1 I can no longer select the corresponding item in Listbox2 by moving the mouse over it. However, selecting by mouseclick still works.

Can someone explain the behaviour and/or provide a solution?

<Window x:Class="Test.sample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="WidthAndHeight">

    <Window.Resources>
        <Style TargetType="ListBox">
            <Style.Setters>
                <Setter Property="Width" Value="150"/>
                <Setter Property="Margin" Value="4"/>
            </Style.Setters>
        </Style>

        <!-- define the XML data source as a resource -->
        <XmlDataProvider x:Key="TestData" XPath="/Books">
            <x:XData>
                <Books xmlns="">
                    <Book>
                        <Title>Book 1</Title>
                        <Author>Mister 1</Author>
                    </Book>
                    <Book>
                        <Title>Book 2</Title>
                        <Author>Mister 2</Author>
                    </Book>
                    <Book>
                        <Title>Book 3</Title>
                        <Author>Mister 3</Author>
                    </Book>
                    <Book>
                        <Title>Book 4</Title>
                        <Author>Mister 4</Author>
                    </Book>
                    <Book>
                        <Title>Book 5</Title>
                        <Author>Mister 5</Author>
                    </Book>
                    <Book>
                        <Title>Book 6</Title>
                        <Author>Mister 6</Author>
                    </Book>
                </Books>
            </x:XData>
        </XmlDataProvider>

    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <StackPanel>
                <Label HorizontalContentAlignment="Center">Listbox 1</Label>
                <ListBox x:Name="box1" ItemsSource="{Binding Source={StaticResource TestData}, XPath=Book}"
                     SelectedItem="{Binding ElementName=box2, Path=SelectedItem, Mode=TwoWay}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding XPath=Title}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
            <StackPanel>
                <Label HorizontalContentAlignment="Center">Listbox 2</Label>
                <ListBox x:Name="box2" ItemsSource="{Binding Source={StaticResource TestData}, XPath=Book}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding XPath=Title}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                    <ListBox.ItemContainerStyle>
                        <Style TargetType="ListBoxItem">
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Padding" Value="12"/>
                                    <Setter Property="IsSelected" Value="True"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </ListBox.ItemContainerStyle>
                </ListBox>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>
+1  A: 

The problem is caused by the two-way binding. When you select an item in ListBox 1, it sets the SelectedItem property on ListBox 2. This "overwrites" the Binding set on ListBox2.SelectedItem. If you want, you can verify in Snoop.

As for how to achieve your goal, you should use a collection view and the IsSynchronizedWithCurrentItem property. Both ListBoxes should bind to the same collection view and be synchronized with the current item. As a result, selecting an item in one ListBox will force the other ListBox to synchronize with that selected item.

Here's the minimum XAML you need to make this happen:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="ListBox">
            <Style.Setters>
                <Setter Property="Width" Value="150"/>
                <Setter Property="Margin" Value="4"/>
            </Style.Setters>
        </Style>

        <!-- define the XML data source as a resource -->
        <XmlDataProvider x:Key="TestData" XPath="/Books">
            <x:XData>
                <Books xmlns="">
                    <Book>
                        <Title>Book 1</Title>
                        <Author>Mister 1</Author>
                    </Book>
                    <Book>
                        <Title>Book 2</Title>
                        <Author>Mister 2</Author>
                    </Book>
                    <Book>
                        <Title>Book 3</Title>
                        <Author>Mister 3</Author>
                    </Book>
                    <Book>
                        <Title>Book 4</Title>
                        <Author>Mister 4</Author>
                    </Book>
                    <Book>
                        <Title>Book 5</Title>
                        <Author>Mister 5</Author>
                    </Book>
                    <Book>
                        <Title>Book 6</Title>
                        <Author>Mister 6</Author>
                    </Book>
                </Books>
            </x:XData>
        </XmlDataProvider>

        <CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource TestData}, XPath=Book}"/>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <StackPanel>
                <Label HorizontalContentAlignment="Center">Listbox 1</Label>
                <ListBox x:Name="box1" ItemsSource="Source={StaticResource cvs}}" IsSynchronizedWithCurrentItem="True">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding XPath=Title}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
            <StackPanel>
                <Label HorizontalContentAlignment="Center">Listbox 2</Label>
                <ListBox x:Name="box2" ItemsSource="{Binding Source={StaticResource cvs}}" IsSynchronizedWithCurrentItem="True">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding XPath=Title}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

HTH,
Kent

Kent Boogaart
Thanks for your suggestion. Unfortunately, the problem persists. As soon as I select an item in Listbox1 it will not anymore get selected in ListBox2 when the IsMouseOver trigger fires.
Sebastian N.
You copied the code above and it doesn't work? Works OK for me.
Kent Boogaart
Your code works but the style trigger of Listbox2 that causes the problem is missing in your example.
Sebastian N.
The style trigger is setting IsSelected, thus overwriting the binding just as described in my answer.
Kent Boogaart
I have looked at the problem with snoop and I'd say it's the other way around: the binding overwrites the styletrigger. I can still select items in both listboxes by clicking them and the same item is selected in the other listbox. The trigger fires but IsSelected is no longer set after selecting the corresponding item in ListBox1. Is there anything that can be done to make that trigger work?
Sebastian N.