问题
Here is a very simple code example:
<DockPanel>
<ToolBar DockPanel.Dock="Top" IsTabStop="False">
<ToggleButton MinWidth="40" Command="EditingCommands.ToggleBold" CommandTarget="{Binding ElementName=XAMLRichBox}" TextBlock.FontWeight="Bold" IsTabStop="False">B</ToggleButton>
</ToolBar>
<RichTextBox x:Name="XAMLRichBox" SpellCheck.IsEnabled="True" MinHeight="100"/>
</DockPanel>
when I run it, after typing something into the RichTextBox
, I can use the ToggleButton
to get the BOLD effect, and everything is fine.
But if I click ToggleButton
before typing in anything into RichTextBox
(no matter RichTextBox
get focus or not), although ToggleButton
became Checked
, my RichTextBox
still using the normal style (not BOLD) until I click ToggleButton
again.
Is this a bug? how can I get around? Thanks!
回答1:
Mainwindow.xaml
<DockPanel>
<ToolBar
DockPanel.Dock="Top"
IsTabStop="False">
<ToggleButton
x:Name="boldButton"
Command="EditingCommands.ToggleBold"
CommandTarget="{Binding ElementName=XAMLRichBox}"
TextBlock.FontWeight="Bold"
ToolTip="Bold">
B
</ToggleButton>
</ToolBar>
<RichTextBox
x:Name="XAMLRichBox"
SpellCheck.IsEnabled="True"
SelectionChanged="SynchronizeWith"
MinHeight="100" />
</DockPanel>
Mainwindow.xaml.cs
private void SynchronizeWith(object sender, RoutedEventArgs e)
{
object currentValue = XAMLRichBox.Selection.GetPropertyValue(TextElement.FontWeightProperty);
boldButton.IsChecked = (currentValue == DependencyProperty.UnsetValue) ? false : currentValue != null && currentValue.Equals(FontWeights.Bold);
}
回答2:
I found a semi-solution and I thought I would share since this problem is not answered anywhere on the web and I think many people are having issues with it.
I set a Variable NewInput in the constructor. When the first input in the richTextBox will be fired, I'll just apply every formating I need to it and pass it to the control.
private bool NewInput;
private void richTxt_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (NewInput)
{
richTxt.BeginChange();
TextPointer startPosition = richTxt.Selection.Start;
Run r = new Run(e.Text, startPosition);
if (IsSelectionBold)
{
r.FontWeight = FontWeights.Bold;
}
if (IsSelectionItalic)
{
r.FontStyle = FontStyles.Italic;
}
if (IsSelectionUnderlined)
{
r.TextDecorations = TextDecorations.Underline;
}
r.FontSize = double.Parse(SelectedFontHeight);
r.FontFamily = new FontFamily(SelectedFont);
richTxt.EndChange();
NewInput = false;
e.Handled = true;
richTxt.CaretPosition = richTxt.CaretPosition.GetPositionAtOffset(1);
}
}
I then replace the carret at the right place. Like this, the formating is kept even if there is nothing in the RichTextBox.
I'm sure it'll help somebody one day.
回答3:
@Sinity was close, but that solution does not work when the caret is placed within the text block, only if it is at the very end.
There are two positions at the end of a Run: Run.ContentEnd
and Run.ElementEnd
. It appears that the ContentEnd
is "just outside" the run (so any new text entered does not take on the run's style), but ElementEnd
is "just inside" the end of the run, and the typed text is added into the run.
Here is a modified solution (that applies a pending Bold style as an example) that seems to work in all cases:
private bool IsBoldStylePending { get; set; }
private void RichTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!IsBoldStylePending)
return;
rtb.BeginChange();
Run run = new Run(e.Text, rtb.CaretPosition); // Add the next character with style
run.FontWeight = FontWeights.Bold;
rtb.EndChange();
rtb.CaretPosition = run.ElementEnd; // Keep caret just within the run
IsBoldStylePending = false;
e.Handled = true;
}
来源:https://stackoverflow.com/questions/7449205/wpf-editingcommands-is-not-working-when-richtextbox-is-just-load-empty