WPF + IoC:“指定的Visual已经是另一个Visual的子项或CompositionTarget的根。”

时间:2009-04-18 04:41:21

标签: wpf spring xaml inversion-of-control

[编辑:重新思考mvvm行的架构使得这个问题在很大程度上消失了 - 谢谢@kent]

使用Spring.NET + WPF。

在配置中加载两个WPF按钮:

<object name="Button1" type="System.Windows.Controls.Button, PresentationFramework" >
  <property name="Name" value="Next" />
  <property name="Width" value="200"/>
  <property name="Content" value="Next"/>
</object>
<object name="Button2" type="System.Windows.Controls.Button, PresentationFramework" >
  <property name="Name" value="Back" />
  <property name="Width" value="200"/>
  <property name="Content" value="Back"/>
</object>   

并将它们传递给xaml类的构造函数(“代码隐藏”)

<object name="MyNewScreen" type="MyControls.MyUserControl>
  <constructor-arg name="buttons">
 <list>
    <ref object="Button1"/>
    <ref object="Button2"/> 
 </list>
 </object>

类构造函数具有:

public DataGridControl(ArrayList buttons)
{
    //(yes this should be a List<Button> but I can't make spring happy with that)
    foreach(var b in buttons) this.stackPanel.Children.Add(b);
    ...

抛出一个:

Specified Visual is already a child of another Visual or the root of a CompositionTarget.

现在,我看到来自Spring的两个按钮的.GetHashCode()是相同的。所以我可以理解WPF不喜欢什么。

但我不能XamlReader.Load(new XmlNodeReader(document));作为some have suggested,而不会丢失我的事件接线。

任何想法如何解决这个问题?

[编辑] 我正在接线活动。事件布线不是问题,但它确实解释了为什么我想首先做这个。为了简洁起见,我把它从原帖中删除了:

<object id="eventListener2" type="MyEventListener">
<listener event="Click" method="b_Click">
<ref object="Button2" />
</listener>
</object>

1 个答案:

答案 0 :(得分:2)

具有相同的哈希码并不意味着对象实例是相同的。检查它们是否实际上是同一个实例的简单方法是在构造函数中设置断点并在监视窗口中计算该表达式:

object.ReferenceEquals(buttons[0], buttons[1])

如果true,它们就是完全相同的对象,那就是你的问题。

那就是说,我认为你更有可能创建多个控件,每个控件都通过Spring配置导入相同的Button

根据Spring documentation,对象的默认范围是singleton。你真正想要的是Spring为每个需要它的控件创建一个Button的新实例。因此,您的配置应该更像这样:

<object name="Button1" type="System.Windows.Controls.Button, PresentationFramework" singleton="false">
  <property name="Name" value="Next" />
  <property name="Width" value="200"/>
  <property name="Content" value="Next"/>
</object>

说了这么多,我认为使用MVVM方法会好得多。您可以让Spring提供视图模型实例(可以无问题地共享)并从该模型生成UI。