WPF EditingCommands is not working when RichTextBox is just load/empty?

荒凉一梦 提交于 2019-12-22 11:08:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!