WPF EditingCommands не работает, когда RichTextBox просто загружен/пуст?

Вот очень простой пример кода:

<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>

когда я запускаю его, набрав что-то в RichTextBox, я могу использовать ToggleButton, чтобы получить эффект BOLD, и все в порядке.

Но если я нажму ToggleButton перед вводом чего-либо в RichTextBox (независимо от того, RichTextBox получит фокус или нет), хотя ToggleButton станет Checked, мой RichTextBox по-прежнему будет использовать обычный стиль (не BOLD), пока я снова не нажму ToggleButton. Это ошибка? как я могу обойти? Спасибо!


person Bolu    schedule 16.09.2011    source источник
comment
Я знаю, что это устарело, но пока вы все еще находитесь на SO, не могли бы вы рассказать нам, нашли ли вы решение этой проблемы? До сих пор без ответа и не только здесь...   -  person Xavier Huppé    schedule 19.06.2014
comment
@Sinity, решение еще не найдено, но ваш ответ ниже выглядит как быстрое решение. Спасибо!   -  person Bolu    schedule 20.06.2014


Ответы (3)


Главное окно.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>    

Главное окно.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);

    }
person Sami    schedule 16.09.2011
comment
спасибо, это синхронизирует статус переключателя с RichTextBox. Но тем не менее, EditingCommands.ToggleBold не будет работать, если пользователь что-то ввел. - person Bolu; 17.09.2011

Я нашел полурешение и подумал, что поделюсь с ним, так как эта проблема нигде не решена в Интернете, и я думаю, что у многих людей возникают проблемы с ней.

Я установил переменную NewInput в конструкторе. Когда будет запущен первый ввод в richTextBox, я просто применю к нему все форматирование, которое мне нужно, и передам его элементу управления.

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);
    }
}

Затем я заменяю каретку в нужном месте. Таким образом, форматирование сохраняется, даже если в RichTextBox ничего нет.

Я уверен, что это поможет кому-то однажды.

person Xavier Huppé    schedule 19.06.2014

@Sinity был близок, но это решение не работает, когда курсор помещается в текстовый блок, только если он находится в самом конце.

В конце Run есть две позиции: Run.ContentEnd и Run.ElementEnd. Похоже, что ContentEnd находится «сразу за пределами» прогона (поэтому любой новый введенный текст не принимает стиль прогона), но ElementEnd находится «сразу внутри» конца прогона, и напечатанный текст добавляется в прогон.

Вот модифицированное решение (в котором в качестве примера применяется отложенный стиль Bold), которое работает во всех случаях:

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;
}
person Jason Williams    schedule 28.06.2017