WPF Listbox SelectedItem改变两次(bug?)

时间:2014-01-11 11:23:02

标签: c# wpf listbox mahapps.metro

我的自定义WPF ListBox有一个非常奇怪的问题:

<Grid Name="root"
      Margin="4"
      Grid.IsSharedSizeScope="True">
    <StackPanel>
        <Grid HorizontalAlignment="Stretch">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="hccFormStyleLabel" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label Target="{Binding ElementName=Theme}"
                   HorizontalAlignment="Left"
                   Grid.Column="0"
                   Content="Theme:">
            </Label>
            <ListBox Grid.Column="1"
                     Name="Theme"
                     SelectionMode="Single"
                     Background="Transparent">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"
                                   IsItemsHost="True" />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBoxItem IsSelected="{Binding IsThemeLight}">
                    <Grid Margin="0 4 4 0"
                          HorizontalAlignment="Center">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="Content" />
                        </Grid.ColumnDefinitions>
                        <StackPanel Orientation="Vertical">
                            <Ellipse Width="16"
                                     Height="16"
                                     StrokeThickness="1"
                                     Stroke="{DynamicResource BlackBrush}"
                                     Fill="{DynamicResource BlackBrush}" />
                            <Label HorizontalAlignment="Center"
                                   Content="Light"></Label>
                        </StackPanel>
                    </Grid>
                </ListBoxItem>
                <ListBoxItem IsSelected="{Binding IsThemeDark}">
                    <Grid Margin="0 4 4 0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="Content" />
                        </Grid.ColumnDefinitions>
                        <StackPanel Orientation="Vertical"
                                    HorizontalAlignment="Center">
                            <Ellipse Width="16"
                                     Height="16"
                                     StrokeThickness="1"
                                     Stroke="{DynamicResource BlackBrush}"
                                     Fill="{DynamicResource WhiteBrush}" />
                            <Label HorizontalAlignment="Center"
                                   Content="Dark"></Label>
                        </StackPanel>
                    </Grid>
                </ListBoxItem>
            </ListBox>
        </Grid>
        <Grid HorizontalAlignment="Stretch">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"
                                  SharedSizeGroup="hccFormStyleLabel"
                                  />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label Target="{Binding ElementName=accentcolors}"
                   HorizontalAlignment="Left"
                   Grid.Column="0"
                   Content="Accent:">
            </Label>
            <ListBox Grid.Column="1"
                     Name="accentcolors"
                     ItemsSource="{Binding AccentColors, Mode=OneWay}"
                     SelectedItem="{Binding ActiveAccent, Mode=TwoWay}"
                     SelectionMode="Single"
                     Background="Transparent">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}}" />
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid Margin="0 4 4 0"
                              HorizontalAlignment="Center">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Content" />
                            </Grid.ColumnDefinitions>
                            <StackPanel Orientation="Vertical"
                                        HorizontalAlignment="Center">
                                <Ellipse Width="16"
                                         Height="16"
                                         Margin="2"
                                         HorizontalAlignment="Center"
                                         Fill="{Binding ColorBrush}" />
                                <TextBlock HorizontalAlignment="Center"
                                           Text="{Binding Path=Name}" />
                            </StackPanel>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </StackPanel>
</Grid>

这将呈现以下样式的列表框:

A B C D

E F G H

I J K L

现在,每当我点击其中一个B-K时,它“随机”选择其中一个项而不是我点击的那个项。

奇怪的是,当我附加调试器并通过所有属性设置器/ getter步进时,一切正常。 当我在没有调试器的情况下运行它(或者不中断)时,会再次出现问题。

我已经将View.Info语句放在viewmodel属性getter和setter上,看起来最初选择了正确的项目。但是在最初的'set_ActiveAccent调用'之后,它再次被调用,在我看来是一个随机值。好像WPF检测到第二次鼠标点击另一个项目。

当我删除I​​temsPanel(WrapPanel)时,它似乎有效,但是使用WrapPanel会回到这种奇怪的行为。

我排除了“宽度”绑定(如果删除它,问题仍然存在)。

有人能告诉我这里发生了什么,或者我如何更好地调查这个?

编辑:好的......这变得更加怪异了。当我使用鼠标右键选择其中一个项目时,它正常工作。所以“鼠标左键单击”发生了一些奇怪的事情

编辑:我将其缩小为'SharedSizeGroup'的问题。我更新了上面的xaml以显示我使用的完整xaml。

当我删除SharedSizeGroup ='hccFormStyleLabel'时(在ColumnDefinition上),一切都重新开始工作。真的没有意义......

我想使用这个共享大小的组,因为在我的应用程序中,我将上面的大部分xaml提取到可重用的HeaderedContentControl。 (为清楚起见,我在我的示例代码中删除了它。)

总而言之:当我设置一个SharedSizeGroup时,我得到了奇怪的双(随机)点击行为。没有它,它就有效。

我能做什么?也许有另一个很好的可重用解决方案来对齐我的表单标签而不是共享的大小组?

2 个答案:

答案 0 :(得分:2)

我发现了正在发生的事情。

正如您可能怀疑的那样,此UI用于更改应用程序的当前主题和重音。

我使用MahApps.Metro的ThemeManager来动态更改应用程序的主题和重点。

事实证明,MahApps ThemeManager调用一些内部WPF方法来使系统资源和缓存无效(在动态更改资源时解决一些问题)。

这与SharedSizeGroup(或一般的布局渲染)相冲突。

目前,我正在使用MahApps.Metro的自定义版本,我禁用此解决方法。

我会将此错误报告给MahApps。

感谢所有人对此进行调查!

答案 1 :(得分:0)

我有一个类似的控件,按预期工作。请看看。

<ListBox ItemsSource="{Binding AccentColors}"
                SelectedItem="{Binding SelectedAccentColor, Mode=TwoWay}"
                Margin="0,0,0,16">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel MaxWidth="{Binding ActualWidth, ElementName=Panel}" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem" BasedOn="{StaticResource FlatListBoxItem}">
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Rectangle Width="40" Height="40" Margin="2" >
                <Rectangle.Fill>
                    <SolidColorBrush x:Name="Brush" Color="{Binding}" />
                </Rectangle.Fill>
            </Rectangle>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>