The only (that I can think of) way to have a variable number of pieces of a text column in different colors (based on two independent values) is to extend the
TextBlock
control to self-construct its content. Here's what I've done.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace WpfApplication3
{
public class NameAvailableTextBlock : TextBlock
{
public string InitialName
{
get { return (string)GetValue(InitialNameProperty); }
set { SetValue(InitialNameProperty, value); }
}
public static readonly DependencyProperty InitialNameProperty =
DependencyProperty.Register("InitialName", typeof(string), typeof(NameAvailableTextBlock), new PropertyMetadata(string.Empty, NameAvailableChanged));
public string Available
{
get { return (string)GetValue(AvailableProperty); }
set { SetValue(AvailableProperty, value); }
}
public static readonly DependencyProperty AvailableProperty =
DependencyProperty.Register("Available", typeof(string), typeof(NameAvailableTextBlock), new PropertyMetadata(string.Empty, NameAvailableChanged));
private static void NameAvailableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((NameAvailableTextBlock)d).DoNameAvailableChanged();
}
private void DoNameAvailableChanged()
{
Inlines.Clear();
string[] names = InitialName.Split('/');
string[] avail = Available.Split('/');
if (names.Length != available.Length)
return;
for (int i = 0; i < names.Length; ++i)
{
if (i > 0)
{
Inlines.Add(new Run("/"));
}
var run = new Run(names[i]);
Inlines.Add(run);
if (avail[i].Trim() == "1")
{
run.Foreground = Brushes.Red;
}
}
}
}
}
and
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<local:NameAvailableTextBlock Width="400"
Height="200"
InitialName="{Binding InitialNames}"
Available="{Binding Available}" />
</Grid>
</Window>
With a DummyDataContext set in MainWindow.xaml.cs:
using System.Windows;
namespace WpfApplication3
{
public partial class MainWindow : Window
{
public class DummyDataContext
{
public string InitialNames { get { return "YVD/LKL/DDS"; } }
public string Available { get { return "1/0/1"; } }
}
public MainWindow()
{
InitializeComponent();
DataContext = new DummyDataContext();
}
}
}
For use in a
DataGrid
, just put the
local:NameAvailableTextBlock
in the template for the column of the grid.
(A full
FlowDocument
probably would be
overkill!)