2013-07-08 73 views
0

這裏 我有一個擴展的richetextbox。在那裏你可以找到帶有動態綁定的datatemplate上的按鈕的文本框, 當我點擊刪除按鈕時它不起作用的問題。 幫助我哪裏出問題了。 這裏是擴展的richetextbox文件。RichTextBox動態資源按鈕事件

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

    namespace Rabbit.Controls 
    { 
     public class RichTextBoxEx:RichTextBox 
     { 
       public bool AutoAddWhiteSpaceAfterTriggered 
       { 
        get { return (bool)GetValue(AutoAddWhiteSpaceAfterTriggeredProperty); } 
        set { SetValue(AutoAddWhiteSpaceAfterTriggeredProperty, value); } 
       } 

       // Using a DependencyProperty as the backing store for AutoAddWhiteSpaceAfterTriggered. This enables animation, styling, binding, etc... 
       public static readonly DependencyProperty AutoAddWhiteSpaceAfterTriggeredProperty = 
        DependencyProperty.Register("AutoAddWhiteSpaceAfterTriggered", typeof(bool), typeof(RichTextBoxEx), new UIPropertyMetadata(true)); 

       public IList<String> ContentAssistSource 
       { 
        get { return (IList<String>)GetValue(ContentAssistSourceProperty); } 
        set { SetValue(ContentAssistSourceProperty, value); } 
       } 

       // Using a DependencyProperty as the backing store for ContentAssistSource. This enables animation, styling, binding, etc... 
       public static readonly DependencyProperty ContentAssistSourceProperty = 
        DependencyProperty.Register("ContentAssistSource", typeof(IList<String>), typeof(RichTextBoxEx), new UIPropertyMetadata(new List<string>())); 

       public IList<char> ContentAssistTriggers 
       { 
        get { return (IList<char>)GetValue(ContentAssistTriggersProperty); } 
        set { SetValue(ContentAssistTriggersProperty, value); } 
       } 

       // Using a DependencyProperty as the backing store for ContentAssistSource. This enables animation, styling, binding, etc... 
       public static readonly DependencyProperty ContentAssistTriggersProperty = 
        DependencyProperty.Register("ContentAssistTriggers", typeof(IList<char>), typeof(RichTextBoxEx), new UIPropertyMetadata(new List<char>())); 

       public static readonly DependencyProperty TokenTemplateProperty = 
        DependencyProperty.Register("TokenTemplate", typeof(DataTemplate), typeof(RichTextBoxEx)); 

       #region constructure 
       public RichTextBoxEx() 
       { 
        this.Loaded += new RoutedEventHandler(RichTextBoxEx_Loaded); 
        TextChanged += OnTokenTextChanged; 
       } 

       void RichTextBoxEx_Loaded(object sender, RoutedEventArgs e) 
       { 
        //init the assist list box 
        if (this.Parent.GetType() != typeof(Grid)) 
        { 
         throw new Exception("this control must be put in Grid control"); 
        } 

        if (ContentAssistTriggers.Count == 0) 
        { 
         ContentAssistTriggers.Add('@'); 
        } 

        (this.Parent as Grid).Children.Add(AssistListBox); 
        AssistListBox.MaxHeight = 100; 
        AssistListBox.MinWidth = 100; 
        AssistListBox.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; 
        AssistListBox.VerticalAlignment = System.Windows.VerticalAlignment.Top; 
        AssistListBox.Visibility = System.Windows.Visibility.Collapsed; 
        AssistListBox.MouseDoubleClick += new MouseButtonEventHandler(AssistListBox_MouseDoubleClick); 
        AssistListBox.PreviewKeyDown += new KeyEventHandler(AssistListBox_PreviewKeyDown); 
       } 

       void AssistListBox_PreviewKeyDown(object sender, KeyEventArgs e) 
       { 
        //if Enter\Tab\Space key is pressed, insert current selected item to richtextbox 
        if (e.Key == Key.Enter || e.Key == Key.Tab || e.Key == Key.Space) 
        { 
         InsertAssistWord(); 
         OnTokenTextChanged(sender, null); 
         e.Handled = true; 
        } 
        else if (e.Key == Key.Back) 
        { 
         //Baskspace key is pressed, set focus to richtext box 
         if (sbLastWords.Length >= 1) 
         { 
          sbLastWords.Remove(sbLastWords.Length - 1, 1); 
         } 
         this.Focus(); 
        } 
       } 

       void AssistListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) 
       { 
        InsertAssistWord(); 
       } 

       private bool InsertAssistWord() 
       { 
        bool isInserted = false; 
        if (AssistListBox.SelectedIndex != -1) 
        { 
         string selectedString = AssistListBox.SelectedItem.ToString().Remove(0, sbLastWords.Length); 
         if (AutoAddWhiteSpaceAfterTriggered) 
         { 
          selectedString += ";"; 
         } 
         this.InsertText(selectedString); 
         isInserted = true; 
        } 

        AssistListBox.Visibility = System.Windows.Visibility.Collapsed; 
        sbLastWords.Clear(); 
        IsAssistKeyPressed = false; 
        return isInserted; 
       } 
       #endregion 

       #region check richtextbox's document.blocks is available 
       private void CheckMyDocumentAvailable() 
       { 
        if (this.Document == null) 
        { 
         this.Document = new System.Windows.Documents.FlowDocument(); 
        } 
        if (Document.Blocks.Count == 0) 
        { 
         Paragraph para = new Paragraph(); 
         Document.Blocks.Add(para); 
        } 
       } 
       #endregion 

       #region Insert Text 
       public void InsertText(string text) 
       { 
        Focus(); 
        CaretPosition.InsertTextInRun(text); 
        TextPointer pointer = CaretPosition.GetPositionAtOffset(text.Length); 
        if (pointer != null) 
        { 
         CaretPosition = pointer; 
        } 
       } 
       #endregion 

       #region Content Assist 
       private bool IsAssistKeyPressed = false; 
       private System.Text.StringBuilder sbLastWords = new System.Text.StringBuilder(); 
       private ListBox AssistListBox = new ListBox(); 

       protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) 
       { 
        if (!IsAssistKeyPressed) 
        { 
         base.OnPreviewKeyDown(e); 
         return; 
        } 

        ResetAssistListBoxLocation(); 

        if (e.Key == System.Windows.Input.Key.Back) 
        { 
         if (sbLastWords.Length > 0) 
         { 
          sbLastWords.Remove(sbLastWords.Length - 1, 1); 
          FilterAssistBoxItemsSource(); 
         } 
         else 
         { 
          IsAssistKeyPressed = false; 
          sbLastWords.Clear(); 
          AssistListBox.Visibility = System.Windows.Visibility.Collapsed; 
         } 
        } 

        //enter key pressed, insert the first item to richtextbox 
        if ((e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Tab)) 
        { 
         AssistListBox.SelectedIndex = 0; 
         if (InsertAssistWord()) 
         { 
          e.Handled = true; 
         } 
        } 

        if (e.Key == Key.Down) 
        { 
         AssistListBox.Focus(); 
        } 

        base.OnPreviewKeyDown(e); 
       } 

       private void FilterAssistBoxItemsSource() 
       { 
        IEnumerable<string> temp = ContentAssistSource.Where(s => s.ToUpper().StartsWith(sbLastWords.ToString().ToUpper())); 
        AssistListBox.ItemsSource = temp; 
        AssistListBox.SelectedIndex = 0; 
        if (temp.Count() == 0) 
        { 
         AssistListBox.Visibility = System.Windows.Visibility.Collapsed; 
        } 
        else 
        { 
         AssistListBox.Visibility = System.Windows.Visibility.Visible; 
        } 
       } 

       protected override void OnTextInput(System.Windows.Input.TextCompositionEventArgs e) 
       { 
        base.OnTextInput(e); 
        if (IsAssistKeyPressed == false && e.Text.Length == 1) 
        { 
         if (ContentAssistTriggers.Contains(char.Parse(e.Text))) 
         { 
          ResetAssistListBoxLocation(); 
          IsAssistKeyPressed = true; 
          FilterAssistBoxItemsSource(); 
          return; 
         } 
        } 

        if (IsAssistKeyPressed) 
        { 
         sbLastWords.Append(e.Text); 
         FilterAssistBoxItemsSource(); 
        } 
       } 

       private void ResetAssistListBoxLocation() 
       { 
        Rect rect = this.CaretPosition.GetCharacterRect(LogicalDirection.Forward); 
        double left = rect.X >= 20 ? rect.X : 20; 
        double top = rect.Y >= 20 ? rect.Y + 20 : 20; 
        left += this.Padding.Left; 
        top += this.Padding.Top; 
        AssistListBox.SetCurrentValue(ListBox.MarginProperty, new Thickness(left, top, 0, 0)); 
       } 
       #endregion 

       public DataTemplate TokenTemplate 
       { 
        get { return (DataTemplate)GetValue(TokenTemplateProperty); } 
        set { SetValue(TokenTemplateProperty, value); } 
       } 

       public Func<string, object> TokenMatcher { get; set; } 

       private void OnTokenTextChanged(object sender, TextChangedEventArgs e) 
       { 
        var text = CaretPosition.GetTextInRun(LogicalDirection.Backward); 
        if (TokenMatcher != null) 
        { 
         var token = TokenMatcher(text); 
         if (token != null) 
         { 
          ReplaceTextWithToken(text, token); 
         } 
        } 
       } 
       private void ReplaceTextWithToken(string inputText, object token) 
       { 
        // Remove the handler temporarily as we will be modifying tokens below, causing more TextChanged events 
        TextChanged -= OnTokenTextChanged; 

        var para = CaretPosition.Paragraph; 

        var matchedRun = para.Inlines.FirstOrDefault(inline => 
        { 
         var run = inline as Run; 
         return (run != null && run.Text.EndsWith(inputText)); 
        }) as Run; 
        if (matchedRun != null) // Found a Run that matched the inputText 
        { 
         var tokenContainer = CreateTokenContainer(inputText, token); 
         para.Inlines.InsertBefore(matchedRun, tokenContainer); 

         // Remove only if the Text in the Run is the same as inputText, else split up 
         if (matchedRun.Text == inputText) 
         { 
          para.Inlines.Remove(matchedRun); 
         } 
         else // Split up 
         { 
          var index = matchedRun.Text.IndexOf(inputText) + inputText.Length; 
          var tailEnd = new Run(matchedRun.Text.Substring(index)); 
          para.Inlines.InsertAfter(matchedRun, tailEnd); 
          para.Inlines.Remove(matchedRun); 
         } 
        } 

        TextChanged += OnTokenTextChanged; 
       } 
       private InlineUIContainer CreateTokenContainer(string inputText, object token) 
       { 
        // Note: we are not using the inputText here, but could be used in future 

        var presenter = new ContentPresenter() 
        { 
         Content = token, 
         ContentTemplate = TokenTemplate, 
        }; 

        // BaselineAlignment is needed to align with Run 
        return new InlineUIContainer(presenter) { BaselineAlignment = BaselineAlignment.TextBottom }; 
       } 
     } 
    } 

這裏的主窗口Xmal位代碼

<Window x:Class="RichTextBoxWithIntellisense.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     Title="Intellisense Rich Text Demo" Height="350" Width="525" xmlns:rabbit="clr-namespace:Rabbit.Controls;assembly=Rabbit.Controls"> 
    <Window.Resources> 
     <LinearGradientBrush x:Key="ClickGradient"> 
      <GradientStop Color="#FF5C2014"/> 
      <GradientStop Color="#FFB0452C"/> 
     </LinearGradientBrush> 
     <LinearGradientBrush x:Key="HoverGradient"> 
      <GradientStop Color="#FF757474"/> 
      <GradientStop Color="#FF918F8F"/> 
     </LinearGradientBrush> 
     <!--<Style x:Key="DeleteButton" TargetType="{x:Type Button}"> 
      <Setter Property="Template"> 
       <Setter.Value>--> 
        <ControlTemplate x:Key="CloseButton" TargetType="{x:Type Button}"> 
          <Grid x:Name="MainGrid"> 
           <Rectangle 
           x:Name="MainRectangle" 
           Fill="#00000000" 
           RadiusX="5" 
           RadiusY="5"/> 
               <ContentPresenter 
          x:Name="Presenter" 
          HorizontalAlignment="Center" 
          VerticalAlignment="Center" 
          TextBlock.Foreground="#BB225588"/> 
               <Path x:Name="Cross" Data="M0,0 L1,1 M0,1 L1,0" Stretch="Fill" 
          Stroke="Black" StrokeThickness="2" Width="8" Height="8" /> 
          </Grid> 
          <!--<StackPanel Orientation="Vertical"> 
           <Path Width="16" Height="16" Fill="#FFFF0000" Stretch="Uniform" 
              Data="M19.85228,12.08996L12.093,19.849201 24.242323,31.997846 12.094,44.145998 19.852051,51.904958 32.001186,39.756277 44.150543,51.904958 51.909,44.145994 39.760246,31.997501 51.909,19.849201 44.15049,12.08996 32.001431,24.238849z M32,0C49.671021,3.1599484E-07 64,14.329407 64,31.998501 64,49.677606 49.671021,63.997003 32,63.997003 14.328003,63.997003 0,49.677606 0,31.998501 0,14.329407 14.328003,3.1599484E-07 32,0z"> 
           </Path> 
          </StackPanel>--> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="MainRectangle" Property="Fill" Value="{StaticResource HoverGradient}"/> 
           <Setter TargetName="MainRectangle" Property="Stroke" Value="Transparent"/> 
           <Setter TargetName="Cross" Property="Stroke" Value="White" /> 
          </Trigger> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter TargetName="MainRectangle" Property="Fill" Value="{StaticResource ClickGradient}"/> 
           <Setter TargetName="Cross" Property="Stroke" Value="White" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       <!--</Setter.Value> 
      </Setter> 
     </Style>--> 
     <DataTemplate x:Key="NameTokenTemplate"> 
      <DataTemplate.Resources> 
        <Storyboard x:Key="OnLoaded1"> 
         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border"> 
          <SplineDoubleKeyFrame KeyTime="0" Value="0"/> 
          <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/> 
         </DoubleAnimationUsingKeyFrames> 
        </Storyboard> 
        <Style x:Key="BtnStyle" TargetType="{x:Type Button}"> 
        <EventSetter Event="Click" Handler="Button_Click"/> 
       </Style> 
      </DataTemplate.Resources> 
      <Border x:Name="border" BorderBrush="#FF7E7E7E" BorderThickness="2" CornerRadius="5" Height="Auto" d:DesignWidth="139" d:DesignHeight="40" Padding="5,3" Margin="3,0,3,3"> 
       <Border.Background> 
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> 
         <GradientStop Color="White" Offset="0"/> 
         <GradientStop Color="LightGray" Offset="1"/> 
        </LinearGradientBrush> 
       </Border.Background> 
       <Grid HorizontalAlignment="Left" Width="Auto"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="0.79*"/> 
         <ColumnDefinition Width="0.21*"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock TextWrapping="NoWrap" Grid.Column="0" Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0,0,0" FontWeight="Bold"/> 
        <Button x:Name="DelBtn" Grid.Column="1" ClickMode="Press" Width="15" Visibility="Visible" HorizontalAlignment="Center" Margin="1" Padding="1,1.5,1,1.5" 
          Template="{StaticResource CloseButton}" 
          Style="{StaticResource BtnStyle}"> 
         <Button.Content> 
          <Path x:Name="Cross" Data="M0,0 L1,1 M0,1 L1,0" Stretch="Fill" Stroke="Black" StrokeThickness="2" Width="8" Height="8" /> 
         </Button.Content> 
        </Button> 
       </Grid> 
      </Border> 
      <DataTemplate.Triggers> 
       <EventTrigger RoutedEvent="FrameworkElement.Loaded"> 
        <BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/> 
       </EventTrigger> 
      </DataTemplate.Triggers> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid Margin="25"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <TextBlock Text="Try to type @ or . in the following rich text box:"/> 
     <Grid Grid.Row="1"> 
      <rabbit:RichTextBoxEx Name="richTextBoxEx1" TokenTemplate="{DynamicResource NameTokenTemplate}" 
          AutoAddWhiteSpaceAfterTriggered="{Binding IsChecked,ElementName=chkAutoAddWhitespace}" 
          ContentAssistTriggers="{Binding ContentAssistTriggers}" 
          ContentAssistSource="{Binding ContentAssistSource}"/> 
     </Grid> 
     <CheckBox x:Name="chkAutoAddWhitespace" Grid.Row="2" Content="AutoAdd White Space After Trigger" IsChecked="True" /> 
    </Grid> 
</Window> 

這裏主窗口後面

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace RichTextBoxWithIntellisense 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public List<String> ContentAssistSource 
     { 
      get { return (List<String>)GetValue(ContentAssistSourceProperty); } 
      set { SetValue(ContentAssistSourceProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for ContentAssisteSource. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty ContentAssistSourceProperty = 
      DependencyProperty.Register("ContentAssistSource", typeof(List<String>), typeof(MainWindow), new UIPropertyMetadata(new List<string>())); 


     public List<char> ContentAssistTriggers 
     { 
      get { return (List<char>)GetValue(ContentAssistTriggersProperty); } 
      set { SetValue(ContentAssistTriggersProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for ContentAssistTriggers. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty ContentAssistTriggersProperty = 
      DependencyProperty.Register("ContentAssistTriggers", typeof(List<char>), typeof(MainWindow), new UIPropertyMetadata(new List<char>())); 


     public MainWindow() 
     { 
      InitializeComponent(); 

      InitRichTextBoxSource(); 
      InitRichTextBoxIntellisenseTrigger(); 
      Loaded += delegate 
      { 
       richTextBoxEx1.Focus(); 
      }; 
      //richTextBoxEx1.Focus(); 
      DataContext = this; 
      richTextBoxEx1.TokenMatcher = text => 
      { 
       if (text.EndsWith(";")) 
       { 
        // Remove the ';' 
        return text.Substring(0, text.Length - 1).Trim().ToUpper(); 
       } 

       return null; 
      }; 
     } 

     private void InitRichTextBoxIntellisenseTrigger() 
     { 
      ContentAssistTriggers.Add('@'); 
      ContentAssistTriggers.Add('.'); 
     } 

     private void InitRichTextBoxSource() 
     { 
      ContentAssistSource.Add("aaal"); 
      ContentAssistSource.Add("as"); 
      ContentAssistSource.Add("aacp"); 
      ContentAssistSource.Add("aid"); 
      ContentAssistSource.Add("asap"); 

      ContentAssistSource.Add("boy"); 
      ContentAssistSource.Add("big"); 
      ContentAssistSource.Add("before"); 
      ContentAssistSource.Add("belong"); 
      ContentAssistSource.Add("can"); 
      ContentAssistSource.Add("clever"); 
      ContentAssistSource.Add("cool"); 
      ContentAssistSource.Add("data"); 
      ContentAssistSource.Add("delete"); 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      // Debug not comin here 
     } 

    } 
} 

回答

-1

答案代碼是設置在RichTextBox爲true IsDocumentEnabled財產。