【发布时间】:2015-01-25 23:40:07
【问题描述】:
我使用FlipView 控件并在ItemTemplate 内部使用Elements 属性创建自定义RichTextBlock,就像Run 元素的集合一样。它可以工作,但是,有时我会收到异常“WinRT 信息:元素已经是另一个元素的子元素。” 我真的不明白为什么。
有人可以解释一下为什么会这样吗?
模型(包含测试数据)
public class Page
{
public Page()
{
Data = new List<Run>();
Data.Add(new Run { Text = "1" });
Data.Add(new Run { Text = "2" });
Data.Add(new Run { Text = "3" });
Data.Add(new Run { Text = "4" });
Data.Add(new Run { Text = "5" });
}
public IList<Run> Data { get; set; }
}
ViewModel(FlipView 的页面集合)
public ObservableCollection<Page> Pages { get; set; }
// test data
Pages = new ObservableCollection<Page>();
Pages.Add(new Page()); // etc
XAML
<FlipView ItemsSource="{Binding Pages}">
<FlipView.ItemTemplate>
<DataTemplate>
<local:ExtendedRichTextBlock Elements="{Binding Data}" />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
ExtendedRichTextBlock
Elements 是依赖属性,变化在这里被捕获:
private static void OnElementsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ExtendedRichTextBlock sender = d as ExtendedRichTextBlock;
if (sender != null)
{
sender.Content.Blocks.Clear();
var x = e.NewValue as IList<Run>;
if (x != null)
{
foreach (var item in x)
{
var p = new Paragraph();
p.Inlines.Add(item); // WinRT information: Element is already the child of another element.
sender.Content.Blocks.Add(p);
}
}
}
}
结论
我在chat 中与 Romasz 讨论的简短结论。
每次触发事件时,您都会清除内容,然后重新使用 Run 元素填充它。在后面它可能非常复杂——可能是一些动画、过渡等等,我也不确定这是否不是异步制作的——如果是这样的话,可能会有元素仍然有父元素并且你尝试重用它的情况。考虑更好的做法,每次都使用 UI 元素填充这不是一个好主意 - 使您的数据模板与这些 UI 元素相结合,并将它们的内容绑定到某种集合。
所以必须在 OnElementsChanged 中动态创建所有元素。
【问题讨论】:
标签: c# xaml windows-phone-8.1 windows-8.1