Search code examples
wpfrichtextboxselectionbehaviorattached-properties

WPF: Attached behavior is registered but never called?


trying my first attached behavior: I want to bind the TextSelection of the RichTextBox to my ViewModel`s property:

public TextSelection SelectedRichText {get;set;}

That way I bind it:

<RichTextBox behavior:RichTextBoxSelectionBehavior.RichTextBoxSelection="{Binding SelectedRichText}" />

Thats my code and I have 2 questions:

1) Why is the OnRichTextBoxSelectionPropertyChanged never called? 2) see the question is this method at bottom: OnRichTextBoxGotSelectedText

public static class RichTextBoxSelectionBehavior
    {

        public static TextSelection GetRichTextBoxSelection(DependencyObject obj)
        {
            return (TextSelection)obj.GetValue(RichTextBoxSelection);
        }

        public static void SetRichTextBoxSelection(DependencyObject obj, TextSelection value)
        {
            obj.SetValue(RichTextBoxSelection, value);
        }

        // Using a DependencyProperty as the backing store for MyProperty.      
        public static readonly DependencyProperty RichTextBoxSelection =
            DependencyProperty.RegisterAttached
            (
                "RichTextBoxSelection", 
                typeof(TextSelection),
                typeof(RichTextBoxSelectionBehavior),
                new UIPropertyMetadata(OnRichTextBoxSelectionPropertyChanged)
            );

        private static void OnRichTextBoxSelectionPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs args)
        {
            RichTextBox rtb = dpo as RichTextBox;

            if (rtb != null)
            {
                if ( !((TextSelection)args.NewValue).IsEmpty)
                {
                    // if the TextSelected has selected text hook up the RichTextBox intenal SelectedChanged event with my own
                    rtb.SelectionChanged += OnRichTextBoxGotSelectedText;
                }
                else
                {
                    rtb.SelectionChanged -= OnRichTextBoxGotSelectedText;
                }
            }
        }

        private static void OnRichTextBoxGotSelectedText(object sender, RoutedEventArgs e)
        {
            RichTextBox rtb = (RichTextBox) sender;

            // How can I pass now my rtb.Selection to the property the behavior is bound to? e.g. my SelectedRichText property in the ViewModel

            //Action action = () => { rtb.Selection; };
            //rtb.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
        }
    }

Solution

  • I mixed up an attached behavior with a dependency property, here is the solution:

    Put a RichTExtBox in a UserControl and this code too:

         // SelectedText property. 
                public static readonly DependencyProperty SelectedTextProperty =
                    DependencyProperty.Register("SelectedText", typeof(TextSelection),
                    typeof(MyRichTextBox ));
    
          /// <summary>
                /// Default constructor.
                /// </summary>
                public MyRichTextBox ()
                {
                    InitializeComponent();
    
                    this.TextBox.SelectionChanged += new RoutedEventHandler(TextBox_SelectionChanged);
                }
    
                void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
                {
                    var sT = (e.OriginalSource as RichTextBox).Selection;
                    SelectedText = sT;
                }
    
    
    
    
       /// <summary>
        /// The WPF Selected Text of the FlowDocument in the control
        /// </summary>
        public TextSelection SelectedText
        {
            get { return (TextSelection)GetValue(SelectedTextProperty); }
            set { SetValue(SelectedTextProperty, value); }
        } 
    
        //UserControl embedded in the MainWindow.xaml
          <My:MyRichTextBox SelectedText="{Binding SelectedDocument,Mode=TwoWay}" x:Name="EditBox" />
    

    Now you have access to the TextSelection of the richtextbox in your ViewModel!