Окрашивание текста в 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 шт):
К сожалению, не могу отыскать ошибку в коде. Если нужны просто цветные строчки, то покажу самое простое решение, почти без привязок.
Можно создать класс модели данных, готовых для отображения.
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;
Выглядеть должно точно так же как на скриншоте.
