我正在使用this网站上的示例来创建MultiColumnStackPanel。
但是有一个问题。加载页面后,stackpanel看起来很好,就像示例一样。但是当我导航到下一页然后返回上一页时,我得到一个例外:
InvalidOperationException使用以下消息:
Element is already the child of another element.
所以我认为原始自定义堆栈面板中包含的项目正被添加到新的自定义堆栈面板中。但是为什么 MultiColumnStackPanel 被“刷新”并且 MultiColumnStackPanel.Items 会持续存在吗?
是否有其他人对此问题有解释/解决方案?
提前致谢
MultiColumnStackPanel类:
public class MultiColumnStackPanel : StackPanel
{
public int NumberOfColumns { get; set; }
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items",
typeof(Collection<UIElement>),
typeof(MultiColumnStackPanel),
new PropertyMetadata(new Collection<UIElement>()));
public Collection<UIElement> Items
{
get { return (Collection<UIElement>)GetValue(ItemsProperty); }
}
public MultiColumnStackPanel()
{
Loaded += (s, e) =>
{
LoadItems();
};
}
void LoadItems()
{
Children.Clear();
if (Items != null)
{
StackPanel sp = CreateNewStackPanel();
foreach (UIElement item in Items)
{
sp.Children.Add(item);
if (sp.Children.Count == NumberOfColumns)
{
Children.Add(sp);
sp = CreateNewStackPanel();
}
}
if (sp.Children.Count > 0)
Children.Add(sp);
}
}
private StackPanel CreateNewStackPanel()
{
Orientation oppositeOrientation;
if(this.Orientation.Equals(Orientation.Vertical))
oppositeOrientation = Orientation.Horizontal;
else
oppositeOrientation = Orientation.Vertical;
return new StackPanel() { Orientation = oppositeOrientation };
}
}
xaml示例:
<model:MultiColumnStackPanel x:Name="customStackPanel" Orientation="Horizontal" NumberOfColumns="2">
<model:MultiColumnStackPanel.Items>
<Rectangle Height="80" Width="80" Margin="10" Fill="Green" />
<Rectangle Height="80" Width="80" Margin="10" Fill="Green" />
<Rectangle Height="80" Width="80" Margin="10" Fill="Green" />
<Rectangle Height="80" Width="80" Margin="10" Fill="Green" />
</model:MultiColumnStackPanel.Items>
</model:MultiColumnStackPanel>
答案 0 :(得分:0)
我想通了,并认为我会分享我的发现。
在MultiColumnStackPanel的构造函数中,函数LoadItems()
绑定到StackPanel的Loaded
事件。
当导航到下一页然后导航回来时,MultiColumnStackPanel没有像我之前想象的那样再次创建。 MultiColumnStackPanel的Loaded
事件再次被触发。
public MultiColumnStackPanel()
{
Loaded += (s, e) =>
{
LoadItems();
};
}
然后我看到每次调用LoadItems()
函数时它都清除了对象的子节点。删除它可以解决问题,如果孩子已经在场,则无需再次从Items
列表中添加它们。
void LoadItems()
{
// Children.Clear();
if (Items != null && (Children == null || Children.Count == 0))
{
StackPanel sp = CreateNewStackPanel();
foreach (UIElement item in Items)
{
sp.Children.Add(item);
if (sp.Children.Count == NumberOfColumns)
{
Children.Add(sp);
sp = CreateNewStackPanel();
}
}
if (sp.Children.Count > 0)
Children.Add(sp);
}
}
有时候你需要一点点自我反思=)
修改强>
还有一点,ItemsProperty
不应该是静态的
public static readonly DependencyProperty ItemsProperty = // <-- remove static
DependencyProperty.Register("Items",
typeof(Collection<UIElement>),
typeof(MultiColumnStackPanel),
new PropertyMetadata(new Collection<UIElement>()));