【问题标题】:Strange behaviour of Listboxes in WPFWPF 中列表框的奇怪行为
【发布时间】:2010-12-13 17:57:39
【问题描述】:

我有一个带有两个ListBoxes 的窗口,它们都绑定到一个XMLDataProviderListbox1SelectedItem 属性双向绑定到 ListBox2SelectedItem 属性。到目前为止一切顺利。

ListBox2 包含一个 Style Trigger,当鼠标悬停在某个项目上时,它会将 IsSelected 设置为 true。由于双向绑定,ListBox1 中的对应项也被选中。当我通过单击在Listbox1 中选择一个项目时,就会出现问题

例如,当我在 ListBox1 中选择“Book 1”,然后将鼠标移到 ListBox2 中的所有项目上时,样式触发器触发时将不再选择项目“Book 1”。一旦我在Listbox1 中选择了一个项目,我就不能再通过将鼠标移到Listbox2 中的相应项目上来选择它。但是,通过鼠标单击选择仍然有效。

有人可以解释这种行为和/或提供解决方案吗?

<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 提供了一个完整的可运行示例和清晰的解释,抱歉不能帮助你.. :)

标签: wpf xaml select binding listbox


【解决方案1】:

问题是由双向绑定引起的。当您在ListBox 1 中选择一个项目时,它会在ListBox 2 上设置SelectedItem 属性。这会“覆盖”在ListBox2.SelectedItem 上设置的Binding。如果您愿意,可以在Snoop 中进行验证。

至于如何实现您的目标,您应该使用集合视图和IsSynchronizedWithCurrentItem 属性。 ListBoxes 都应该绑定到同一个集合视图并与当前项目同步。因此,在一个 ListBox 中选择一个项目将强制另一个 ListBox 与该选定项目同步。

这是实现此目的所需的最低 XAML:

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

【讨论】:

  • 感谢您的建议。不幸的是,问题仍然存在。一旦我在 Listbox1 中选择了一个项目,当 IsMouseOver 触发器触发时,它将不再在 ListBox2 中被选中。
  • 你复制了上面的代码,它不起作用?对我来说没问题。
  • 您的代码有效,但您的示例中缺少导致问题的 Listbox2 的样式触发器。
  • 样式触发器正在设置 IsSelected,因此正如我的回答中所述覆盖绑定。
  • 我已经查看了 snoop 的问题,我想说这是相反的:绑定覆盖了样式触发器。我仍然可以通过单击两个列表框中的项目来选择它们,并且在另一个列表框中选择了相同的项目。触发器触发,但在 ListBox1 中选择相应项目后不再设置 IsSelected。有什么办法可以使该触发器起作用吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
相关资源
最近更新 更多