为什么ComboBox会下拉导致整个应用程序性能变得非常慢?

时间:2010-10-23 01:40:19

标签: wpf performance

我有一个wpf应用程序。有一个奇怪的事情,只要我mousedown ComboBox droparrow成为所有UI响应非常慢,无论ComboBox是否有项目。 烦人的情况只出现在一些计算机上。 期待回答。

2 个答案:

答案 0 :(得分:3)

我已经找到了你可以在互联网上找到的提示,我只是注意到没有问题。

应谨慎遵循以下事项,因为否则虚拟化已经消失(取自MSDN,link):

  • 项目容器直接添加到ItemsControl。例如,如果应用程序显式将ListBoxItem对象添加到ListBox,则ListBox不会虚拟化ListBoxItem对象。
  • 将CanContentScroll设置为false。
  • 将IsVirtualizing设置为false。
  • 使用项目分组。

以下风格对我没有任何问题。

<Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <VirtualizingStackPanel IsItemsHost="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" KeyboardNavigation.DirectionalNavigation="Contained" />
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

<ComboBox Name="cbTest" IsEditable="True" Style="{StaticResource SimpleComboBox}" />


在我用Kaxaml的风格玩了一会儿之后,我注意到了一件小事。使用这种风格时,我使用IsEditable = "True"时遇到了问题,性能下降了!

以下风格适合我完美

<Style x:Key="SimpleComboBox" TargetType="{x:Type ComboBox}">
  <Setter Property="SnapsToDevicePixels" Value="true"/>
  <Setter Property="OverridesDefaultStyle" Value="true"/>
  <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
  <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
  <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
  <Setter Property="MinWidth" Value="120"/>
  <Setter Property="MinHeight" Value="20"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ComboBox}">
        <Grid>
          <ToggleButton Name="ToggleButton" Focusable="false" ClickMode="Press"
                        IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
            <ToggleButton.Template>
              <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Grid>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition Width="20" />
                  </Grid.ColumnDefinitions>
                  <Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="2" Background="#C0C0C0" BorderBrush="#404040" BorderThickness="1" />
                  <Border Grid.Column="0" CornerRadius="2,0,0,2" Margin="1" Background="#FFFFFF" BorderBrush="#404040" BorderThickness="0,0,1,0" />
                  <Path x:Name="Arrow" Grid.Column="1" Fill="#404040" HorizontalAlignment="Center" VerticalAlignment="Center" Data="M 0 0 L 4 4 L 8 0 Z"/>
                </Grid>
                <ControlTemplate.Triggers>
                  <Trigger Property="ToggleButton.IsMouseOver" Value="true">
                    <Setter TargetName="Border" Property="Background" Value="#808080" />
                  </Trigger>
                  <Trigger Property="ToggleButton.IsChecked" Value="true">
                    <Setter TargetName="Border" Property="Background" Value="#E0E0E0" />
                  </Trigger>
                  <Trigger Property="IsEnabled" Value="False">
                    <Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
                    <Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
                    <Setter Property="Foreground" Value="#888888"/>
                    <Setter TargetName="Arrow" Property="Fill" Value="#888888" />
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </ToggleButton.Template>
          </ToggleButton>
          <ContentPresenter Name="ContentSite" IsHitTestVisible="False"
            Content="{TemplateBinding SelectionBoxItem}"
            ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
            ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
            Margin="3,3,23,3"
            VerticalAlignment="Center"
            HorizontalAlignment="Left" />
          <TextBox x:Name="PART_EditableTextBox" Style="{x:Null}" HorizontalAlignment="Left" VerticalAlignment="Center"
                   Margin="3,3,23,3" Focusable="True" Background="Transparent" Visibility="Hidden" IsReadOnly="{TemplateBinding IsReadOnly}">
            <TextBox.Template>
              <ControlTemplate TargetType="{x:Type TextBox}">
                <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
              </ControlTemplate>
            </TextBox.Template>
          </TextBox>
          <Popup Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
            <Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxDropDownHeight}">
              <Border x:Name="DropDownBorder" Background="#FFFFFF" BorderThickness="1" BorderBrush="#888888"/>
              <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                <VirtualizingStackPanel IsItemsHost="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling" KeyboardNavigation.DirectionalNavigation="Contained" />
              </ScrollViewer>
            </Grid>
          </Popup>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="HasItems" Value="false">
            <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
          </Trigger>
          <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="#888888"/>
          </Trigger>
          <!-- remove this trigger, because the virtualization is broken!!!
          <Trigger Property="IsGrouping" Value="true">
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
          </Trigger>
          -->                
          <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
            <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
            <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
          </Trigger>
          <Trigger Property="IsEditable"
                   Value="true">
            <Setter Property="IsTabStop" Value="false"/>
            <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
            <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
  </Style.Triggers>
</Style>

我也删除了这个触发器。

<Trigger Property="IsGrouping" Value="true">
  <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>

希望这有帮助

答案 1 :(得分:2)

由于您提到ComboBox中没有数据时仍然存在同样的问题,我怀疑这是造型问题。

ComboBox默认样式中,受鼠标悬停影响的唯一因素是ButtonChrome内的ToggleButton控件,您可以在其中展开CombBox

<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" SnapsToDevicePixels="true">

您可以先尝试删除代码

RenderMouseOver="{TemplateBinding IsMouseOver}"

或使用Border完全替换它(请注意,您还需要删除IsChecked触发器)

<Border x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">

并查看问题是否已消失。

我不是100%确定导致它的原因,如果您可以发布您的xaml代码会很有帮助。 :)