2009-07-05 8 views
11

Ich kann mir das komplett vorstellen, aber ich hätte schwören können, dass es einen Weg gab, einzelne Run (oder Parapgraph) -Elemente in einer RichTextBox schreibgeschützt zu machen. Ich hätte auch geschworen ich eine Methode versucht, dies zu tun vor ein paar Wochen selbst und war zufrieden mit den Ergebnissen - ich erinnere mich vage, es ist etwas so aussah:Schreibgeschützt Ausführen von Elementen in einer WPF RichTextBox?

<RichTextBox x:Name="richTextBox" 
      AcceptsTab="True" 
      AcceptsReturn="True" 
      FontFamily="Courier New" 
      FontSize="14"> 
    <FlowDocument> 
     <Paragraph> 
      <Run IsReadOnly="True">I wish this was read-only!</Run> 
     </Paragraph> 
    </FlowDocument> 
</RichTextBox> 

Jetzt, ein paar Wochen später, ich gehe Versuchen, Run-Elemente schreibgeschützt in einer RichTextBox zu machen, nur um sie zu finden, scheint nicht möglich zu sein.

This post on the MSDN forums scheint dies zu bestätigen.

Darf ich mir das komplett vorstellen? Oder gibt es eine Möglichkeit zu tun, was ich tun möchte?

Antwort

7

In Ordnung, ich habe eine Lösung gefunden, die für meinen Fall funktioniert - aber möglicherweise nicht für jeden funktioniert, der so etwas möchte. Es ist unordentlich, aber es macht den Job.

Ich werde meine eigene Antwort für ein paar Tage nicht akzeptieren, nur für den Fall, dass jemand anders einen besseren Weg hat, dies zu erreichen.

Hier gehen wir zunächst die XAML:

<Window x:Class="WpfApplication1.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" 
     Height="500" 
     Width="600"> 
    <DockPanel LastChildFill="True"> 
     <RichTextBox x:Name="rtb" 
        FontFamily="Courier New" 
        FontSize="14" 
        PreviewKeyDown="rtb_PreviewKeyDown"> 
      <FlowDocument> 
       <Paragraph> 
        <InlineUIContainer Unloaded="InlineUIContainer_Unloaded"> 
         <TextBlock FontFamily="Courier New" FontSize="14">This line of text is not editable.</TextBlock> 
        </InlineUIContainer> 
        <Run Foreground="Blue">But this is editable.</Run> 
       </Paragraph> 
      </FlowDocument> 
     </RichTextBox> 
    </DockPanel> 
</Window> 

Und den Code hinter:

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 

namespace WpfApplication1 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 

     private void InlineUIContainer_Unloaded(object sender, RoutedEventArgs e) 
     { 
      (sender as InlineUIContainer).Unloaded -= new RoutedEventHandler(InlineUIContainer_Unloaded); 

      TextBlock tb = new TextBlock(); 
      tb.FontFamily = new FontFamily("Courier New"); 
      tb.FontSize = 14; 
      tb.Text = "This line of text is not editable."; 

      TextPointer tp = rtb.CaretPosition.GetInsertionPosition(LogicalDirection.Forward); 
      InlineUIContainer iuic = new InlineUIContainer(tb, tp); 
      iuic.Unloaded += new RoutedEventHandler(InlineUIContainer_Unloaded); 
     } 

     private void rtb_PreviewKeyDown(object sender, KeyEventArgs e) 
     { 
      if (e.Key == Key.Enter) 
      { 
       var newPointer = rtb.Selection.Start.InsertLineBreak(); 
       rtb.Selection.Select(newPointer, newPointer); 

       e.Handled = true; 
      } 
     } 
    } 
} 

Meine Lösung beruht auf der Tatsache, dass, wenn ein InlineUIContainer von der Benutzeroberfläche entfernt wird, ist es Unloaded() Methode wird aufgerufen. An diesem Punkt lege ich einfach die gelöschte InlineUIContainer an der aktuellen Caret-Position wieder ein.

Wie bei jedem Hack gibt es eine Reihe von Nachteilen. Die folgenden Nachteile sind die folgenden:

  • Der Text, den ich schreibgeschützt sein möchte, muss in eine InlineUIContainer verpackt werden. Das ist ein wenig einschränkend für diese Lösung.
  • Ich muss die 'Enter'-Taste erfassen und Zeilenumbrüche manuell einfügen, ansonsten wird InlineUIContainer.Unloaded() immer ausgelöst, wenn die Eingabetaste gedrückt wird. Nicht lustig, aber es funktioniert für meinen Fall.

Es ist keine großartige Lösung, aber ich denke, es wird für mich arbeiten. Wie ich schon sagte, werde ich das hier nicht als eine Antwort auf meine eigene Frage bezeichnen - hoffentlich wird jemand anderes einen besseren Weg finden, dies zu tun.

+2

Sehr interessant es mir hinzufügen helfen "Widgets", wenn Sie in den Texteditor gehen. Ich mache einen sehr schönen Windows-Wiki-Editor. Zum Hinzufügen von Bildern, Kategorien und Schlüsselwörtern verwende ich kleine Objekte, die das Rich Text-Objekt dekorieren. Ich wünschte, der Redakteur wäre ein bisschen mehr wie der Redakteur des visuellen Studios. Auf diese Weise konnte ich "Verzierungen" hinzufügen, aber ... das hat mir definitiv geholfen! Vielen Dank. – JustinKaz

+0

Ich bin froh, dass es helfen könnte - seien Sie gewarnt, aber - ich erinnere mich vage daran, dass es möglich ist, schreibgeschützten Text mit der Rücktaste zu löschen.Nach dieser ganzen Zeit bin ich mir nicht sicher, aber ich würde es gründlich testen, um sicherzustellen, dass die Widgets schreibgeschützt bleiben. –

1

Dies kann durch den Umgang mit zwei Ereignissen erreicht werden: 1) OnMouseDown 2) OnPreviewKeyDown

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Controls; 
using System.Windows; 
using System.Windows.Input; 

namespace WpfApplication2 
{ 
public class MultiPartTextBox : TextBox 
{ 
    private string _prefix; 
    private string _content; 

    public string Prefix 
    { 
     get { return _prefix; } 
     set { _prefix = value; 
     Text = _prefix; 
     } 
    } 

    public string Content 
    { 
     get { return _content; } 
     set { 
      _content = value; 
      Text = _prefix + _content; 
     } 
    } 

    public MultiPartTextBox() { _prefix = string.Empty; } 

    protected override void OnMouseDown(MouseButtonEventArgs e) 
    { 

     base.OnMouseDown(e); 
     this.SelectionStart = _prefix.Length; 
     this.SelectionLength = 0; 
    } 

    //tab In 
    protected override void OnGotFocus(RoutedEventArgs e) 
    { 
     this.SelectionStart = _prefix.Length; 
     this.SelectionLength = 0; 
     base.OnGotFocus(e); 
    } 

    protected override void OnPreviewKeyDown(KeyEventArgs e) 
    { 
     if (e.Key == Key.Back 
      || e.Key == Key.Delete 
      || e.Key==Key.Left) 
     { 
      if (CaretIndex <= _prefix.Length) 
      { 
       e.Handled = true; 
       return; 
      } 
     } 
     base.OnPreviewKeyDown(e); 
    } 
    } 
    } 

in XAML wir es in folgenden Weise zu behandeln haben:

xmlns:uc="clr-namespace:WpfApplication2" 

     <uc:MultiPartTextBox Height="30" HorizontalAlignment="Left" 
      Margin="80,94,0,0" x:Name="multiPartTxt1" VerticalAlignment="Top" 
      Width="224" Prefix="NON-EDITABLE" CaretIndex="4" >    
     </uc:MultiPartTextBox> 
+0

Sie haben Fingerberührungen vergessen. – McKay

Verwandte Themen