2011-09-16 2 views
3

Voici un exemple de code très simple:WPF EditingCommands ne fonctionne pas lorsque RichTextBox est juste chargé/vide?

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

quand je le lance, après avoir tapé quelque chose dans le RichTextBox, je peux utiliser le ToggleButton pour obtenir le BOLD effet, et tout va bien.

Mais si je clique ToggleButton avant de taper quoi que ce soit dans dans RichTextBox (peu importe RichTextBox se concentrer ou non), bien que ToggleButton est devenu Checked, mon RichTextBox en utilisant toujours le style normal (pas BOLD) jusqu'à ce que je clique ToggleButton à nouveau. Est-ce un bug? comment puis-je me déplacer? Merci!

+0

Je sais que c'est vieux, mais pendant que vous êtes encore à ce SO Pourriez-vous nous dire si vous avez trouvé une solution à ce problème? Il est encore sans réponse et pas seulement ici ... –

+0

@Sinity, aucune solution trouvée pour l'instant, mais votre réponse ci-dessous ressemble à une solution rapide. Merci! – Bolu

Répondre

3

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

    } 
+1

merci, cela synchronisera l'état de togglebutton avec le 'RichTextBox'. Mais encore, 'EditingCommands.ToggleBold' ne fonctionnera pas util utilisateur entré quelque chose. – Bolu

3

J'ai trouvé une demi-solution et je pensais que je partage depuis ce problème ne répond pas partout sur le web et je pense que beaucoup de gens ont des problèmes avec ça. J'ai défini une variable NewInput dans le constructeur. Lorsque la première entrée de la zone richTextBox sera déclenchée, j'appliquerai tout ce dont j'ai besoin et je la passerai au contrôle.

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

Puis remplacer le carret au bon endroit. Comme ceci, le formatage est conservé même s'il n'y a rien dans le RichTextBox.

Je suis sûr que ça va aider quelqu'un un jour.

0

@Sinity était proche, mais cette solution ne fonctionne pas lorsque le curseur est placé dans le bloc de texte, seulement s'il se trouve à la toute fin. Il existe deux positions à la fin d'un cycle: Run.ContentEnd et Run.ElementEnd. Il semble que le ContentEnd soit "juste en dehors" de la course (donc tout nouveau texte entré ne prend pas le style de la course), mais ElementEnd est "juste à l'intérieur" de la fin de la course, et le texte tapé est ajouté à la course.

est ici une solution modifiée (qui applique une attente de style gras comme un exemple) qui semble fonctionner dans tous les cas:

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; 
} 
Questions connexes