Dependency property (attached behavior) is not updated by attached property (other attached behavior)

WPF.

In XAML, I have a Canvas that will contain TextBlocks whose placement is determined by the information gathered from the RichTextBox control. Both Canvas and RichTextBox have added behavior that adds an "Outline" property.

My goal is to set the RichTextBox outline property from the RichTextBoxSelectionChanged event. The outline property will constantly change as you enter text into the RichTextBox.

I need the "OutlineCanvas" to get the changes to the Outline property and act on it by placing TextBlocks in the assoicate Canvas.

For reasons I cannot get, the code below sets the "Outline" to the RichTextBox, but it is NOT picked up by the OutlineCanvas.

The behavior for OutlineCanvas appears to be triggered by ONCE, but it does not perceive the Outline set in the RichTextBox behavior.

Where am I going wrong? How to do it?

TIA

XAML
<Canvas Grid.Column="0" Name="OutlineCanvas" Background="Azure" >
                    <i:Interaction.Behaviors>
                        <b:OutlineBehavior Outline="{Binding ElementName=RichTextControl, Path=(b:RichTextBehavior.Outline)}"/> 
                    </i:Interaction.Behaviors>
                </Canvas>

  <RichTextBox x:Name="RichTextControl" Grid.Column="1"
                               a:SmartAdorner.Visible="{Binding TranscriptionLayer.IsAdornerVisible}"
                                Panel.ZIndex="{Binding TranscriptionLayer.ZIndex}"  Cursor="IBeam"                               
                                Height="{Binding VirtualPage.Height}" 
                                Visibility="{Binding Path=TranscriptionLayer.Visibility}"  
                             SpellCheck.IsEnabled="True" 
                             VerticalScrollBarVisibility="Auto" 
                             AcceptsReturn="True" AcceptsTab="True"
                            >

 <i:Interaction.Behaviors>    
                        <b:RichTextBehavior 
                                SelectedText="{Binding  TranscriptionLayer.SelectedText}"                              
                                Image="{Binding TranscriptionLayer.Image}"
                                MoveImage="{Binding TranscriptionLayer.MoveImage}"
                                DeleteImage="{Binding TranscriptionLayer.DeleteImage}"
                            />
                    </i:Interaction.Behaviors>



C#
public class OutlineBehavior : Behavior<Canvas>
    {
        // The XAML attaches the behavior when it is instantiated.
        protected override void OnAttached()
        {
            base.OnAttached();
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
        }



        public static ProgressNoteOutline GetOutline(DependencyObject obj)
        {
            return (ProgressNoteOutline)obj.GetValue(OutlineProperty);
        }

        public static void SetOutline(DependencyObject obj, ProgressNoteOutline value)
        {
            obj.SetValue(OutlineProperty, value);
        }

        // Using a DependencyProperty as the backing store for Outline.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OutlineProperty =
            DependencyProperty.Register("Outline", typeof(ProgressNoteOutline), typeof(OutlineBehavior),
            new FrameworkPropertyMetadata(null, OnOutlineChanged));

        private static void OnOutlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            OutlineBehavior behavior = d as OutlineBehavior;
            if (behavior == null)
                return;

            Canvas canv = behavior.AssociatedObject as Canvas;
            if (canv == null)
                return;

            ProgressNoteOutline _outline = (ProgressNoteOutline)e.NewValue;
            if (_outline == null)
                return;

            OutlineItem[] _items = _outline.items;
            foreach (OutlineItem t in _items)
            {
                TextBlock tb = new TextBlock();
                tb.Background = Brushes.AntiqueWhite;
                tb.TextAlignment = TextAlignment.Left;
                tb.Inlines.Add(new Italic(new Bold(new Run(t.text))));

                Canvas.SetLeft(tb, 0);
                Canvas.SetTop(tb, t.Y);

                canv.Children.Add(tb);
            }

        }

The RichTextBox property (in its behavior):
 public ProgressNoteOutline Outline
        {
            get { return (ProgressNoteOutline)GetValue(OutlineProperty); }
            set { SetValue(OutlineProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Outline.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OutlineProperty =
            DependencyProperty.RegisterAttached("Outline", typeof(ProgressNoteOutline), typeof(RichTextBehavior),
            new FrameworkPropertyMetadata(new ProgressNoteOutline());

      

Finally, in the behavior of the RichTextBox, the Outline is set as:

 var _items = new OutlineItem[100];
            for (int i = 0; i < 100; i++)
            {
                _items[i] = new OutlineItem { Y = i * 30, text = string.Format("Title {0}", i) };
            }
            Outline = new ProgressNoteOutline { items = _items };

      

+3


source to share


1 answer


I cannot figure out how this binding is supposed to work - from one behavior to another. So what kind of work was it to subclass the canvas like:

    public class OutlineCanvas : Canvas
    {

        public ProgressNoteOutline Outline
        {
            get { return (ProgressNoteOutline)GetValue(OutlineProperty); }
            set { SetValue(OutlineProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Outline.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OutlineProperty =
                DependencyProperty.Register("Outline", 
                typeof(ProgressNoteOutline), typeof(OutlineCanvas),
                 new FrameworkPropertyMetadata(null, OnOutlineChanged));

        private static void OnOutlineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            OutlineCanvas canv = d as OutlineCanvas;
            if (canv == null)
                return;           

            ProgressNoteOutline _outline = (ProgressNoteOutline)e.NewValue;
            if (_outline == null)
                return;

            OutlineItem[] _items = _outline.items;
            if (_items == null)
                return;

            foreach (OutlineItem t in _items)
            {
                TextBlock tb = new TextBlock();
                tb.Background = Brushes.AntiqueWhite;
                tb.TextAlignment = TextAlignment.Left;
                tb.Inlines.Add(new Italic(new Bold(new Run(t.text))));

                SetLeft(tb, 0);
                SetTop(tb, t.Y);

                canv.Children.Add(tb);
            }
        }
    }

      

Then change the XAML as:



 <b:OutlineCanvas Grid.Column="0" x:Name="OutlineCanvas" Background="Azure" />

<b:RichTextBehavior               
       Outline="{Binding ElementName=OutlineCanvas, Path=Outline}" />

      

Hope this helps someone :)

0


source







All Articles