2016-03-03 99 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單元格? –