You know how you're reading an article and it explains how to do something cool, and you think "That's interesting, I'll remember you can do that" but you don't bother to remember the details? I did that many years ago when I read that TextBlocks can have Runs. They are sequences of characters with different characteristics in the same TextBlock. You can do the same thing with rtf but it's very complicated so I didn't really pay much attention at the time.
I came across a requirement recently that could be solved by making parts of the text in a TextBlock invisible at run time so I created the runs in code. Here's an example of doing it in XAML and then I'll do it again in code.
Start a Visual Studio 2019 WPF Application (Core) project in C#. Call it Runs. We will add a TextBlock and two combo boxes to the MainWindow. The TextBlock will have two runs and the combo boxes will control the font size in the two runs. The XAML looks like this...
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Runs"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<TextBlock>
<TextBlock.Inlines>
<Run Text="Hello" FontSize="{Binding FontSize1}"/>
<Run Text=" "/>
<Run Text="World" FontSize="{Binding FontSize2}"/>
</TextBlock.Inlines>
</TextBlock>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding FontSizes}" SelectedItem="{Binding FontSize1}" Width="50"/>
<ComboBox ItemsSource="{Binding FontSizes}" SelectedItem="{Binding FontSize2}" Width="50"/>
</StackPanel>
</StackPanel>
</Window>
using System.ComponentModel;
using System.Windows;
namespace Runs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public double[] FontSizes
get { return new double[] { 8, 10, 12, 14, 16, 20 }; }
private double _FontSize1 = 12;
get { return _FontSize1; }
{
_FontSize1 = value;
}
}
private double _FontSize2 = 12;
get { return _FontSize2; }
{
_FontSize2 = value;
}
}
public MainWindow()
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
if (PropertyChanged != null)
}
}
Here is the same thing done in code...
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Runs"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<TextBlock Initialized="TextBlock_Initialized"/>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding FontSizes}" SelectedItem="{Binding FontSize1}" Width="50"/>
<ComboBox ItemsSource="{Binding FontSizes}" SelectedItem="{Binding FontSize2}" Width="50"/>
</StackPanel>
</StackPanel>
</Window>
using System.ComponentModel;
namespace Runs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public double[] FontSizes
get { return new double[] { 8, 10, 12, 14, 16, 20 }; }
private double _FontSize1 = 12;
get { return _FontSize1; }
{
_FontSize1 = value;
}
}
private double _FontSize2 = 12;
get { return _FontSize2; }
{
_FontSize2 = value;
}
}
public MainWindow()
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
if (PropertyChanged != null)
private void TextBlock_Initialized(object sender, EventArgs e)
TextBlock tb = (TextBlock)sender;
Binding b1 = new Binding("FontSize1") { Source = this };
tb.Inlines.Clear();
tb.Inlines.Add(r1);
tb.Inlines.Add(r2);
tb.Inlines.Add(r3);
}
}
}
No comments:
Post a Comment