C#,WPF - datagrid-cell中的多种颜色(syntaxhighlighting)

时间:2016-04-26 07:52:45

标签: c# wpf xaml datagrid converter

我为我的datagrid开发了一些syntaxhighlighting和syntaxchecking:

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 = ClientSettings.getInstance();

    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 )");


    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {

        if (!clientSettings.SyntaxCheck && !clientSettings.SyntaxHighlighting || String.IsNullOrEmpty(values[0] as String))
            return values[0];

        SAPConnector sapConnector = SAPConnector.getInstance();
        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.Brown, strings.Matches(input));
                    assignColor(Brushes.DeepPink, subFormula.Matches(input));
                    assignColor(Brushes.Green, sapFormula.Matches(input));
                    assignColor(Brushes.Green, not.Matches(input));

                    int index = 0;
                    foreach (Char character in input)
                    {
                        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":
                            try
                            {
                                if (!calcFormulaCache.ContainsKey(input))
                                    calcFormulaCache.Add(input, sapConnector.variantConfigurationTestDAO.vcCalculateFormula3(input, true));

                                syntaxResult = calcFormulaCache[input];
                            }
                            catch (Exception ex)
                            {
                                textBlock.TextDecorations.Add(textDec);
                                textBlock.ToolTip = "Syntaxüberprüfung fehlgeschlagen: " + ex.Message;
                                Logger.getInstance().writeLogEntry(Logger.LogLevel.ERROR, String.Format("Syntaxcheckfehler: Die Kalkulationsformel '{0}' konnte nicht überprüft werden --> {1}", input, ex.Message), ex.StackTrace);
                            }
                            break;
                        case "MATCHEXPRESSION":
                            try
                            {
                                if (!matchExpressionCache.ContainsKey(input))
                                    matchExpressionCache.Add(input, sapConnector.variantConfigurationTestDAO.vcEvalMatchEx(input, true));

                                syntaxResult = matchExpressionCache[input];
                            }
                            catch (Exception ex)
                            {
                                textBlock.TextDecorations.Add(textDec);
                                textBlock.ToolTip = "Syntaxüberprüfung fehlgeschlagen: " + ex.Message;
                                Logger.getInstance().writeLogEntry(Logger.LogLevel.ERROR, String.Format("Syntaxcheckfehler: Die Ausdrucksformel '{0}' konnte nicht überprüft werden --> {1}", input, ex.Message), ex.StackTrace);
                            }

                            break;
                        default:
                            break;
                    }


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

                            if (syntaxResult.errors.Count == 0)
                                textBlock.ToolTip = "Allgemeiner Syntaxfehler";
                            else
                            {
                                List<String> groupedErrors = new List<String>();
                                foreach (String error in syntaxResult.errors)
                                {
                                    if (groupedErrors.FirstOrDefault(x => x == error) == null)
                                        groupedErrors.Add(error);
                                }

                                textBlock.ToolTip = String.Join(Environment.NewLine, groupedErrors);
                            }
                        }
                    }
                }

                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";
                    }
                }
            }
        }

        ToolTipService.SetShowDuration(textBlock, 999999);
        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;
            }
        }
    }

}

它基本上有效。问题是它变得非常缓慢,因为在我看来有两个原因:每一行都需要一个转换器调用,我将每一个字符串分开,然后将一个文本块内联到它(很多垃圾?)

这是我的xaml datagrid的一列:

<DataGridTextColumn Binding="{Binding TopLevelGroup, IsAsync=False}" x:Name="cTopLevelGroup" MinWidth="150" Visibility="Visible">
                <DataGridTextColumn.HeaderStyle>
                    <Style TargetType="{x:Type DataGridColumnHeader}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="auto"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="auto"/>
                                            <ColumnDefinition Width="auto"/>
                                            <ColumnDefinition Width="auto"/>
                                        </Grid.ColumnDefinitions>

                                        <Label Grid.Column="1" Padding="5 0" Content="Gruppe"  FontWeight="Bold" VerticalAlignment="Center" Cursor="Hand" Foreground="White"/>
                                        <TextBox x:Name="txtTopGroupFilter" Margin="0 5" Grid.Column="2" Width="150" Visibility="Collapsed"/>
                                        <Button Grid.Column="3" Margin="5 0" x:Name="btnFilterTopGroup" Style="{StaticResource MyButton}" Width="16" Height="16" VerticalAlignment="Center" HorizontalAlignment="Right" Click="btnFilterTopGroup_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="3"
                    HorizontalAlignment="Right"
                    Width="2" 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>
                </DataGridTextColumn.HeaderStyle>

            </DataGridTextColumn>

和datagrid本身:

<DataGrid x:Name="dgVarConfig"
              ItemsSource="{Binding VarConfigList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
              SelectedItem="{Binding SelectedVarConfig, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
              Margin="10,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"

              VirtualizingPanel.IsVirtualizing="true"
              EnableRowVirtualization="True"
              EnableColumnVirtualization="false"
              VirtualizingPanel.VirtualizationMode="Recycling"
              VirtualizingPanel.IsVirtualizingWhenGrouping="True"
              ScrollViewer.CanContentScroll="False"
             >

是否有任何变化可以让它更快一点?越多,我得到的越慢。此刻大约有500行,但这种增长非常非常快。

0 个答案:

没有答案