【发布时间】:2019-08-21 14:34:15
【问题描述】:
我目前正在使用包含工具栏和 RichTextBox 的 WPF 编写文本编辑器。工具栏中的每个按钮定义将应用于所选文本的文本属性(使用 costum 属性)。它工作正常。
问题
如果用户单击文本上的某处,并且将其文本属性应用于当前位置,则应突出显示按钮。当我尝试检查当前选择是否带下划线/删除线时,它不起作用。
代码
private void checkToolBarButtons()
{
// this method checks if the button should be highlighted or not.
Func<Button, object> check = (Button button) =>
{
try
{
// the button has two costum properties that allow to determine which text property should be
// applied to the selected text.
string propString = ToolBarButton.GetDocumentProperty(button);
// e.g. "TextDecorations"
DependencyProperty dependency = this.getPropertyByString(propString);
// e.g. TextDecorationsProperty
string propertyValue = ToolBarButton.GetDocumentPropertyValue(button);
// e.g. "Underline"
if (dependency != null)
{
TextRange selectionRange = new TextRange(this.richTextBox.Selection.Start, this.richTextBox.Selection.End);
object selectedProperty = selectionRange.GetPropertyValue(dependency);
if (selectedProperty.GetType() == typeof(TextDecorationCollection) && ((TextDecorationCollection)selectedProperty).Count > 0)
{
if (selectedProperty.Equals(TextDecorations.Underline))
{
// this code is never reached
selectedProperty = "Underline";
}
else if (selectedProperty.Equals(TextDecorations.Strikethrough))
{
// this code is never reached
selectedProperty = "Strikethrough";
}
}
if (selectedProperty.ToString() == propertyValue)
{
button.Background = new SolidColorBrush(Colors.Yellow);
}
else
{
button.Background = new SolidColorBrush(Colors.LightGray);
}
}
}
catch (Exception ex)
{
}
return null;
};
foreach (FrameworkElement ctrl in toolBar.Children)
{
if (ctrl.GetType() == typeof(StackPanel))
{
foreach (Button button in ((Panel)ctrl).Children)
{
check(button);
}
}
else if (ctrl.GetType() == typeof(Button))
{
check((Button)ctrl);
}
}
}
/// <summary>
/// converts a string to a DependencyProperty
/// </summary>
/// <param name="propertyString"></param>
/// <returns></returns>
private DependencyProperty getPropertyByString(string propertyString)
{
switch (propertyString)
{
case ("FontStyleProperty"): return FontStyleProperty;
case ("FontWeightProperty"): return FontWeightProperty;
case ("TextDecorations"): return TextBlock.TextDecorationsProperty;
case ("TextAlignment"): return TextBlock.TextAlignmentProperty;
default:
break;
}
return null;
}
XAML
<UserControl x:Class="EasyControls.TextEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:EasyControls"
mc:Ignorable="d" Height="236.318" Width="493.571">
<Border BorderThickness="1" BorderBrush="Blue">
<DockPanel Background="White">
<WrapPanel x:Name="toolBar" Orientation="Horizontal" Background="#FF2B2B8F" DockPanel.Dock="Top">
<StackPanel x:Name="textAlignPanel" Background="#FFF4F4F5" Height="21" Orientation="Horizontal" Margin="2">
<Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Left"
Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
<Image Source="img/Left.png" />
</Button>
<Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Center"
Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
<Image Source="img/Center.png" />
</Button>
<Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Right"
Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
<Image Source="img/Right.png" />
</Button>
<Button local:ToolBarButton.DocumentProperty="TextAlignment" local:ToolBarButton.DocumentPropertyValue="Justify"
Margin="2 2 2 2" Click="ToolBarButton_Click" Width="20">
<Image Source="img/Justify.png" />
</Button>
</StackPanel>
<StackPanel x:Name="fontStylePanel" Background="#FFF4F4F5" Height="21" Orientation="Horizontal">
<Button local:ToolBarButton.DocumentProperty="FontWeightProperty" local:ToolBarButton.DocumentPropertyValue="Bold"
Margin="2 2 2 2" Click="ToolBarButton_Click" FontWeight="Bold" Width="20">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">b</TextBlock>
</Button>
<Button local:ToolBarButton.DocumentProperty="FontStyleProperty" local:ToolBarButton.DocumentPropertyValue="Italic"
Margin="1 2 2 2" Click="ToolBarButton_Click" FontStyle="Italic" Width="20">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">i</TextBlock>
</Button>
<Button local:ToolBarButton.DocumentProperty="TextDecorations" local:ToolBarButton.DocumentPropertyValue="Underline"
Margin="1 2 2 2" Click="ToolBarButton_Click" Width="20" >
<TextBlock TextDecorations="Underline" HorizontalAlignment="Center" VerticalAlignment="Center">u</TextBlock>
</Button>
<Button local:ToolBarButton.DocumentProperty="TextDecorations" local:ToolBarButton.DocumentPropertyValue="Strikethrough"
Margin="1 2 2 2" Click="ToolBarButton_Click" Width="20" >
<TextBlock TextDecorations="Strikethrough" HorizontalAlignment="Center" VerticalAlignment="Center">s</TextBlock>
</Button>
</StackPanel>
</WrapPanel>
<RichTextBox x:Name="richTextBox" Background="White" SelectionChanged="RichTextBox_SelectionChanged" IsDocumentEnabled="True" DockPanel.Dock="Bottom" VerticalAlignment="Stretch" BorderThickness="0" BorderBrush="{x:Null}">
<FlowDocument>
<Paragraph/>
</FlowDocument>
</RichTextBox>
</DockPanel>
</Border>
【问题讨论】:
-
也许你应该试试this。
-
@geronimo678 是的,我在重建您未显示的 XAML 时出错。我在下划线按钮上有
local:ToolBarButton.DocumentProperty="FontStyleProperty",而不是local:ToolBarButton.DocumentProperty="TextDecorations"。一旦我解决了这个问题,只要我在富文本框中的选择发生变化时调用checkToolBarButtons(),你的代码就可以像你写的那样为我工作。 -
@geronimo678 感谢您添加 XAML。你知道,那些附加的属性可能是枚举。让我感兴趣的是,如果集合包含
x,TextDecorationCollection.Equals(x)返回 true。 -
@EdPlunkett 你完全正确,我应该使用枚举。 Equals() 方法对我不起作用(请参阅我对帖子答案的第一条评论)。
-
@geronimo678 好的,我明白了:TextDecorations.Underline 是 TextDecorationCollection 的一个实例,其中包含一个 TextDecorationLocation,
Underline。TextDecorations.Strikethrough也是一个包含一个项目的集合。当所选文本带有下划线且未被删除时,selectedProperty实际上是同一个对象实例,因此 Equals() 返回 true 并且您的代码有效(对我而言)。如果文本带有下划线和删除线,则您的检查都不正确,因为selectedProperty是一个不同的集合,其中包含两个项目。