Почему ComboBox приводит к снижению производительности всего приложения? - PullRequest
2 голосов
/ 23 октября 2010

У меня есть wpf-приложение. Странно, что, пока я копирую, выпадающий список ComboBox очень медленно реагирует на весь интерфейс, независимо от того, есть ли в ComboBox элементы.Раздражающий случай появляется только на некоторых компьютерах.С нетерпением ждем ответа.

Ответы [ 2 ]

3 голосов
/ 19 декабря 2011

Я просмотрел советы, которые вы можете найти в Интернете, и только что заметил, что проблем нет.

Следующим вещам следует тщательно следовать, потому что в противном случае виртуализация исчезнет (взято из MSDN ссылка ):

  • Контейнеры элементов добавляются непосредственно в 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>

Надеюсь, это поможет

2 голосов
/ 19 декабря 2011

Поскольку вы упомянули, что у вас все еще остается та же проблема, когда в 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.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...