2016-03-03 92 views
0

我有一个非常大的Datagrid。缓慢的datagrid - 提高性能

这里只有一列的数据网格:

<DataGrid x:Name="dgVarConfig" 
       ItemsSource="{Binding VarConfigList, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
       SelectedItem="{Binding Path=SelectedVarConfig, Mode=TwoWay}" 
       Margin="8,56,557,80" 
       AutoGenerateColumns="False" 
       CanUserDeleteRows="False" 
       CanUserResizeRows="False" 
       HeadersVisibility="Column" 
       CanUserAddRows="False" 
       HorizontalScrollBarVisibility="Auto" 
       PreviewKeyDown="dgVarConfig_PreviewKeyDown" 
       BeginningEdit="dgVarConfig_BeginningEdit" 
       CellEditEnding="dgVarConfig_CellEditEnding" 
       SelectionChanged="dgVarConfig_SelectionChanged" 
       EnableRowVirtualization="True" 
       EnableColumnVirtualization="False" 
       VerticalGridLinesBrush="Black" 
       VirtualizingStackPanel.VirtualizationMode ="Standard" 
       VirtualizingStackPanel.IsVirtualizing="true"> 


<DataGrid.Columns> 
    <DataGridTemplateColumn Width="auto" MinWidth="150" SortMemberPath="Match_expression"> 

     <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate> 
         <ContentControl> 
          <MultiBinding Converter="{StaticResource highlightConverter}" ConverterParameter="MATCHEXPRESSION"> 
           <Binding Path="Match_expression"></Binding> 
          </MultiBinding> 
         </ContentControl> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 

       <DataGridTemplateColumn.CellEditingTemplate > 
        <DataTemplate> 
         <TextBox Text="{Binding Match_expression}" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" Style="{StaticResource GridTextBox}"></TextBox> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellEditingTemplate> 

       <DataGridTemplateColumn.HeaderStyle> 
        <Style TargetType="DataGridColumnHeader"> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="DataGridColumnHeader"> 
            <Grid> 
             <Grid.ColumnDefinitions> 
              <ColumnDefinition Width="auto"></ColumnDefinition> 
              <ColumnDefinition Width="*"></ColumnDefinition> 
              <ColumnDefinition Width="auto"></ColumnDefinition> 
              <ColumnDefinition Width="auto"></ColumnDefinition> 
              <ColumnDefinition Width="auto"></ColumnDefinition> 
             </Grid.ColumnDefinitions> 

             <Label Grid.Column="1" Padding="5 0" Content="Auswahlformel" VerticalAlignment="Center" Cursor="Hand" Foreground="White"/> 
             <TextBox x:Name="txtMatchExpressionFilter" Margin="0 5" Grid.Column="2" Width="150" Visibility="Collapsed"></TextBox> 
             <Button Grid.Column="3" Margin="5 0" x:Name="btnFilterMatchExpresion" Style="{StaticResource MyButton}" Width="16" Height="16" VerticalAlignment="Center" HorizontalAlignment="Right" Click="btnFilterMatchExpresion_Click"> 
              <Button.Background> 
               <ImageBrush ImageSource="Resources/filter.png"/> 
              </Button.Background> 
             </Button> 

             <Path x:Name="SortArrow" 
             Grid.Column="0" 
             HorizontalAlignment="Right" VerticalAlignment="Center"           
             Width="8" Height="6" Margin="2,0,5,0" 
             Stretch="Fill" Opacity="0.5" Fill="White" 
             RenderTransformOrigin="0.5,0.4" 
             Visibility="Collapsed" 
             Data="M0,0 L1,0 0.5,1 z" /> 

             <Thumb x:Name="PART_RightHeaderGripper" Grid.Column="4" HorizontalAlignment="Right" Width="1" BorderThickness="1" 
               BorderBrush="{Binding VerticalGridLinesBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" Cursor="SizeWE"/> 
            </Grid> 


            <ControlTemplate.Triggers> 
             <Trigger Property="SortDirection" Value="Ascending"> 
              <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" /> 
              <Setter TargetName="SortArrow" Property="RenderTransform"> 
               <Setter.Value> 
                <RotateTransform Angle="180" /> 
               </Setter.Value> 
              </Setter> 
             </Trigger> 
             <Trigger Property="SortDirection" Value="Descending"> 
              <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" /> 
             </Trigger> 
            </ControlTemplate.Triggers> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </DataGridTemplateColumn.HeaderStyle> 

    </DataGridTemplateColumn> 
</DataGrid.Columns> 

<DataGrid.GroupStyle> 
      <GroupStyle> 
       <GroupStyle.ContainerStyle> 
        <Style TargetType="{x:Type GroupItem}"> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="{x:Type GroupItem}"> 
            <StackPanel Background="Gray" Margin="-5 0 0 0"> 
             <TextBlock Foreground="White" FontWeight="Bold" Text="{Binding Path=Name, StringFormat=Gruppe: {0}}" Margin="10 5 0 5"/> 
             <ItemsPresenter /> 
            </StackPanel> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </GroupStyle.ContainerStyle> 
      </GroupStyle> 

      <GroupStyle> 
       <GroupStyle.HeaderTemplate> 
        <DataTemplate> 
         <DockPanel Background="LightGray"> 
          <TextBlock Text="{Binding Path=Name}" Foreground="Black" Margin="10 2 0 2"/> 
          <ItemsPresenter></ItemsPresenter> 
         </DockPanel> 
        </DataTemplate> 
       </GroupStyle.HeaderTemplate> 
      </GroupStyle> 
</DataGrid.GroupStyle> 

<DataGrid.ContextMenu> 
    <ContextMenu> 
    <MenuItem x:Name="cmAddGroup" Header="Gruppe zuweisen" Click="cmAddGroup_Click" ></MenuItem> 
    <MenuItem x:Name="cmRemoveDeleteFlag" Header="Löschvermerk entfernen" Click="cmRemoveDeleteFlag_Click"></MenuItem> 
    </ContextMenu>   
</DataGrid.ContextMenu> 

让我解释一下:

“highlightConverter”检查单元格的值,并做某种语法突显,syntaxcheck和收益有色TextBlock

如果我想编辑那TextBlock我不得不将它转换为TextBox

网格有两个组(我还没有发布的所有列,因此该组不在这里,但GroupStyle

两个有我加入他们在这里太SortingArrows。 在每一列的Header中都有一个filterButton来过滤行。

这使我我的问题:网格沾到过滤真的很慢,整理,调整行/列,列重新排序,滚动等 我觉得因为TextBlockTextBox这两个项目的。有没有更好的解决方案来提高性能?

这里的HighlightConverter.cs

public class HighlightConverter : IMultiValueConverter 
{ 
    public static Dictionary<String, SyntaxResult> calcFormulaCache; 
    public static Dictionary<String, SyntaxResult> matchExpressionCache; 

    public HighlightConverter() 
    { 
     calcFormulaCache = new Dictionary<string, SyntaxResult>(); 
     matchExpressionCache = new Dictionary<string, SyntaxResult>(); 
    } 

    ClientSettings clientSettings = new ClientSettings(); 

    Brush[] colorArray; 

    Regex subFormula = new Regex(@"\w+\(\)"); 
    Regex sapFormula = new Regex(@"\w+\(([^)]+)\)"); 
    Regex strings = new Regex(@"\'[^']+\'"); 
    Regex numerals = new Regex(@"\b[0-9\.]+\b"); 
    Regex characteristic = new Regex(@"(?:)?\w+(?:)?"); 
    Regex andOr = new Regex(@"(and)|(AND)|(or)|(OR)"); 
    Regex not = new Regex(@"(not)|(NOT)"); 

    VariantConfigurationTestDAO variantConfigurationTestDAO = new VariantConfigurationTestDAO(); 


    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!clientSettings.SyntaxCheck && !clientSettings.SyntaxCheck) 
      return values[0]; 

     TextBlock textBlock = new TextBlock(); 

     string input = values[0] as String; 

     if (!String.IsNullOrEmpty(input)) 
     { 
      if (clientSettings.SyntaxHighlighting) 
      { 
       colorArray = new Brush[input.Length]; 

       for (int i = 0; i < input.Length; i++) 
        colorArray[i] = Brushes.Black; 

       //Reihenfolge beibehalten!! 
       assignColor(Brushes.Blue, characteristic.Matches(input)); 
       assignColor(Brushes.Black, andOr.Matches(input)); 
       assignColor(Brushes.Black, numerals.Matches(input)); 
       assignColor(Brushes.Orange, strings.Matches(input)); 
       assignColor(Brushes.DeepPink, subFormula.Matches(input)); 
       assignColor(Brushes.Green, sapFormula.Matches(input)); 
       assignColor(Brushes.Green, not.Matches(input)); 

       List<Char> splittedInput = input.ToCharArray().ToList(); 
       int index = 0; 
       foreach (Char character in splittedInput) 
       { 
        textBlock.Inlines.Add(new Run(character.ToString()) { Foreground = colorArray[index] }); 
        index++; 
       } 

       colorArray = null; 
      } 
      else 
      { 
       colorArray = null; 
       textBlock.Text = input; 
      } 

      if (clientSettings.SyntaxCheck) 
      { 
       Pen pen = new Pen(Brushes.Red, 3); 
       TextDecoration textDec = new TextDecoration(TextDecorationLocation.Underline, pen, 4, TextDecorationUnit.Pixel, TextDecorationUnit.FontRecommended); 


       if (!String.IsNullOrEmpty((String)parameter)) 
       { 
        String para = (String)parameter; 
        SyntaxResult syntaxResult = null; 

        switch (para) 
        { 
         case "VARIANT": 
          if (para == "VARIANT") 
          { 
           if (characteristic.IsMatch(input) || subFormula.IsMatch(input)) 
           { 
            if (andOr.IsMatch(input) || numerals.IsMatch(input) || strings.IsMatch(input) || sapFormula.IsMatch(input) || not.IsMatch(input)) 
            { 
             textBlock.TextDecorations.Add(textDec); 
             textBlock.ToolTip = "Hier darf nur ein Merkmal oder eine Subformel stehen"; 
            } 
           } 
          } 
          break; 
         case "CALCFORMULA": 
          if (!calcFormulaCache.ContainsKey(input)) 
           calcFormulaCache.Add(input, variantConfigurationTestDAO.vcCalculateFormula3(input, true)); 

          syntaxResult = calcFormulaCache[input]; 
          break; 
         case "MATCHEXPRESSION": 
          if (!matchExpressionCache.ContainsKey(input)) 
           matchExpressionCache.Add(input, variantConfigurationTestDAO.vcEvalMatchEx(input, true)); 


          syntaxResult = matchExpressionCache[input];; 
          break; 
         default: 
          break; 
        } 


        if (syntaxResult != null) 
        { 
         if (syntaxResult.syntax > 0) 
         { 
          textBlock.TextDecorations.Add(textDec); 

          if (syntaxResult.errors.Count == 0) 
           textBlock.ToolTip = "Allgemeiner Syntaxfehler"; 
          else 
           textBlock.ToolTip = String.Join(",", syntaxResult.errors); 
         } 
        } 

       } 

       if (values.Count() == 2) 
       { 
        string input2 = values[1] as String; 

        if (String.IsNullOrEmpty(input2)) 
        { 
         textBlock.TextDecorations.Add(textDec); 
         textBlock.ToolTip = "Es müssen Variante und Kalkulationsformel gefüllt sein"; 
        } 
       } 
      } 
     } 



     return textBlock; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 


    private void assignColor(Brush brush, MatchCollection matchCollection) 
    { 
     foreach (Match match in matchCollection) 
     { 
      int start = match.Index; 
      int end = start + match.Length; 

      for (int i = start; i < end; i++) 
      { 
       colorArray[i] = brush; 
      } 
     } 
    } 

} 
+0

您在任何一个时间点执行此操作的行数是多少?在单行上执行highlightconverter是否显着缓慢 - 或者是否在所有行上运行此方法? – wazdev

+0

我在每一行运行highlightconverter。目前大约有100排,但未来会有几千个。但装载不是问题。我可以等。问题是慢滚动,过滤,诉诸,调整大小等 –

回答

2

在我看来,这是不使用IMultiConverter,但VirtualizationColumn Rendering的问题。

尝试使用这些属性的DataGrid中:

  • 一格
  • 设置VirtualizingStackPanel.IsVirtualizing = “真” 的DataGrid中启用VirtualizingStackPanel.VirtualizationMode
  • MaxWidth = “2560” MaxHeight =” 1600“

Never put a DataGrid in a ScrollViewer, because you will essentially lose virtualization

例如:

<DataGrid ItemsSource="{Binding EmployeeDataTable, IsAsync=True}" 
      VirtualizingStackPanel.IsVirtualizing="true" EnableRowVirtualization="True" 
     EnableColumnVirtualization="True" MaxWidth="2560" MaxHeight="1600" 
     VirtualizingStackPanel.VirtualizationMode="Recycling" 
     VirtualizingPanel.IsVirtualizingWhenGrouping="True"/> 
+0

加载方式更快,但它有点laggy当垂直滚动 –

+0

我不知道它的英文名称..我认为口吃?它的速度慢:D –

+0

加载速度稍慢一些。但垂直慢速滚动消失了。水平滚动再次缓慢:D –

1

你有相当大的Convert方法。想象一下,它调用DataGrid中的每个单元格。

  1. 尝试对其他线程进行语法分析。对于用户来说,它将看起来像 - 输入文本,并在几秒钟内检查和/或突出显示语法。

  2. Regex.Matches使用延迟初始化,所以当你迭代通过匹配 - 它实际上每次都在基于正则表达式的字符串中执行搜索。尝试在Convert()中排除assignColor方法组并检查执行时间。如果有帮助 - 尝试编写自己的字符串解析器,而不使用正则表达式。

  3. 在这一行List<Char> splittedInput = input.ToCharArray().ToList();您正在通过input字符迭代两次。第一次 - 当您从字符串字符创建数组时,第二次 - 当您从数组项创建列表时。然后你在foreach (Char character in splittedInput)中通过这个字符串再次迭代。你实际上可以遍历input本身:foreach (var character in input)

  4. 在这一行:if (values.Count() == 2)使用.Length(阵列的性能),而不是.Count()(扩展LINQ方法),因为在时间序列的每个时刻都知道它的长度,并调用扩展LINQ方法的原因,处理阵列像IEnumerable延迟初始化。

但我认为主要问题是在连续文本分析。频繁的解决方案是在并行线程中执行字符串分析 - 用于非暂停用户输入(或对此执行任何操作)。

+0

如何更改另一个线程中的datagrid单元格? –