我有一个非常大的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来过滤行。
这使我我的问题:网格沾到过滤真的很慢,整理,调整行/列,列重新排序,滚动等 我觉得因为TextBlock
和TextBox
这两个项目的。有没有更好的解决方案来提高性能?
这里的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;
}
}
}
}
您在任何一个时间点执行此操作的行数是多少?在单行上执行highlightconverter是否显着缓慢 - 或者是否在所有行上运行此方法? – wazdev
我在每一行运行highlightconverter。目前大约有100排,但未来会有几千个。但装载不是问题。我可以等。问题是慢滚动,过滤,诉诸,调整大小等 –