【发布时间】: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 的目标行为永远不会被触发——无论我使用什么语法。以我的简单思维方式,似乎行为必须连接到具体对象,或者将对象与行为联系起来——而不是行为与行为之间(如果这有意义吗?)。我肯定会感谢知道这一点的人的意见。