【问题标题】:Dependency property (of an attached behavior) is not being updated by an attached property (of another attached behavior)(附加行为的)依赖属性没有被(另一个附加行为的)附加属性更新
【发布时间】:2017-03-27 05:36:44
【问题描述】:

WPF。

在 XAML 中,我有一个 Canvas 将保存 TextBlock,其位置由从 RichTextBox 控件收集的信息确定。 Canvas 和 RichTextBox 都附加了添加“Outline”属性的行为。

我的目标是让 RichTextBox 从其 RichTextBoxSelectionChanged 事件中设置大纲属性。将文本输入到 RichTextBox 中时,大纲属性将不断变化。

我需要“OutlineCanvas”来获取 Outline 属性中的更改,并通过将 TextBlocks 放置在关联的 Canvas 中来对其进行操作。

由于我无法理解的原因,下面的代码确实在 RichTextBox 中设置了“大纲”,但 OutlineCanvas 并未拾取它。

看起来 OutlineCanvas 的行为似乎启动了一次,但它并没有拾取在 RichTextBox 行为中设置的 Outline。

我哪里错了?这应该怎么做?

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

最后,在 RichTextBox 行为中,Outline 被设置为:

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

【问题讨论】:

  • 尝试在绑定中设置双向模式?
  • @WPFUser 是的。没用。
  • 能发一下 RichTextBoxBehavior 代码吗?
  • @WPFUser 当然......但它相当长,而且大部分与手头的问题无关。如果你确定你想要它,我很乐意发布它,但我认为我在原始帖子的附加属性声明中包含了最重要的部分。 :)
  • @WPFUser 出于我不知道的原因,当从一个行为到另一个行为时,OutlineCanvas 的目标行为永远不会被触发——无论我使用什么语法。以我的简单思维方式,似乎行为必须连接到具体对象,或者将对象与行为联系起来——而不是行为与行为之间(如果这有意义吗?)。我肯定会感谢知道这一点的人的意见。

标签: c# wpf xaml


【解决方案1】:

我似乎无法理解这个绑定应该如何工作——从一种行为到另一种行为。那么起作用的是将画布子类化为:

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

然后将 XAML 更改为:

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

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

希望它可以帮助某人:)

【讨论】:

    猜你喜欢
    • 2015-11-25
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多