Окрашивание текста в TetBlock

При окрашивании текста в TextBlock с помощью TextRange в TextBlock появляется новая строка, если окраска произошла 2-ух и более строк в разный цвет. Цвета и диапазон беру из базы данных. Код и пример неправильной работы ниже.

        public void ChangeColorText(DependencyObject container, DataSet dataSet)
        {
            TextPointer start_position = null;
            TextPointer end_position = null;

            DataTable ColorDataTable = dataSet.Tables[dataSet.Tables.Count - 1];

            if (container is TextBlock)
            {
                start_position = ((TextBlock)container).ContentStart;
                end_position = ((TextBlock)container).ContentStart;
            }
            else if (container is FlowDocument)
            {
                start_position = ((FlowDocument)container).ContentStart;
                end_position = ((FlowDocument)container).ContentStart;
            }
            
            TextRange[] coloredTextRanges = new TextRange[ColorDataTable.Rows.Count];
            for(int i = 0; i < coloredTextRanges.Length; i++)
                coloredTextRanges[i] = new TextRange(start_position, end_position);

            int textRangeIndex = 0;

            foreach (DataRow dataRow in ColorDataTable.Rows)
            {
                var cells = dataRow.ItemArray; 

                DataRow allTextDataRow = dataSet.Tables[0].Rows[0];
                string text = allTextDataRow[cells[3].ToString()].ToString();

                if (container is TextBlock)
                {
                    if(textRangeIndex == 0)
                        ((TextBlock)container).Text = text;
                    start_position = ((TextBlock)container).ContentStart.GetPositionAtOffset((int)cells[0]);
                    end_position = ((TextBlock)container).ContentStart.GetPositionAtOffset((int)cells[1] + 1);
                }
                else if (container is FlowDocument)
                {
                    if (textRangeIndex == 0)
                        ((TextBlock)container).Text = text;
                    ((FlowDocument)container).Blocks.Add(new Paragraph(new Run(text)));
                    start_position = ((FlowDocument)container).ContentStart.GetPositionAtOffset((int)cells[0]);
                    end_position = ((FlowDocument)container).ContentStart.GetPositionAtOffset((int)cells[1] + 1);
                }
                
                coloredTextRanges[textRangeIndex] = new TextRange(start_position, end_position);
                coloredTextRanges[textRangeIndex].Text = (text[(int)cells[0]-1] == '\n' && textRangeIndex == 0) ? text.Substring((int)cells[0], (int)cells[1] - (int)cells[0]) : "\n" + text.Substring((int)cells[0], (int)cells[1] - (int)cells[0]);//textRangeIndex > 0 ? (int)cells[1] - (int)cells[0] - 2 : (int)cells[1] - (int)cells[0]
                coloredTextRanges[textRangeIndex].ApplyPropertyValue(TextElement.ForegroundProperty, (SolidColorBrush)new BrushConverter().ConvertFromString((string)cells[2]));
                textRangeIndex++;
            }
        }

Пример неправильного поведения

По итогу все стало выглядеть вот так:

        public class RowColorModel
        {
            public string Text { get; set; }
            public SolidColorBrush Color { get; set; }
        }

        public class RowColorReader
        {
            public List<RowColorModel> coloredRows { get; set; }

            void GetTextFromDataSet(DataSet dataSet)
            {
                this.coloredRows = new List<RowColorModel>();

                List<DataTable> contentDataTables = new List<DataTable>();
                for (int i = 0; i < dataSet.Tables.Count - 1; i++)
                    contentDataTables.Add(dataSet.Tables[i]);

                foreach (DataTable contentDataTable in contentDataTables)
                {
                    foreach (DataRow contentDataRow in contentDataTable.Rows)
                        foreach (var cell in contentDataRow.ItemArray)
                            foreach (string str in cell.ToString().Split('\n'))
                                this.coloredRows.Add(new RowColorModel
                                {
                                    Text = str.Replace('\r', ' ')
                                });
                }
            }
            public void ToFormColoredTextOnDataSet(DataSet dataSet)
            {
                GetTextFromDataSet(dataSet);
                DataTable coloredDataTable = dataSet.Tables[dataSet.Tables.Count - 1];

                foreach(var contentItem in this.coloredRows)
                    contentItem.Color = new SolidColorBrush(Colors.Black);

                foreach (DataRow dataRow in coloredDataTable.Rows)
                {
                    var cells = dataRow.ItemArray;
                    coloredRows[(int)cells[0]].Color = (SolidColorBrush)new BrushConverter().ConvertFromString((string)cells[1]);
                }
            }
        }

Ответы (1 шт):

Автор решения: aepot

К сожалению, не могу отыскать ошибку в коде. Если нужны просто цветные строчки, то покажу самое простое решение, почти без привязок.

Можно создать класс модели данных, готовых для отображения.

public class RowModel
{
    public string Text { get; set; }
    public SolidColorBrush Brush { get; set; }
}

Можно создать список

List<RowModel> items = new List<RowModel>();

Можно его наполнить, так же в цикле, как вы выводите данные, только здесь без заморочек с контролами

items.Add(new RowModel
{
    Text = ...
    Brush = ...
});

Можно создать представление этого списка в интерфейсе

<ItemsControl x:Name="myItemsControl">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text}" Foreground="{Binding Brush}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

И просто закинуть этот список в представление

myItemsControl.ItemsSource = items;

Выглядеть должно точно так же как на скриншоте.

→ Ссылка