7

我正在使用 MV-VM 模式

在我的虚拟机中,我有类似的代码

public class ViewModel {
    public XmlDocument Document { ... }
    ....
}

我有一个标记扩展,我想从中使用所述文档

  public override object ProvideValue(IServiceProvider serviceProvider) {
        IProvideValueTarget valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        if (valueProvider != null) {
            DependencyObject target = valueProvider.TargetObject as DependencyObject;
            XmlDocument doc = Foo.GetDocument(target);
            if (doc != null) {
                var n = doc.SelectSingleNode("/.../text()");
                if (n != null) return n.Value;
            }
        }
        return "«" + ObjectProperty + "»";
    }

我创建了附加属性 Foo.Document,并将其附加到我的页面(页面的 DataContext 设置为我的 ViewModel 类的实例

<Page ... lc:Foo.Document="{Binding Document}">
  ...
</Page>

(为了不必每次使用标记扩展时都将其作为参数输入)

现在,在我的标记扩展中,当我尝试读取 Document 附加属性时,我总是得到一个空文档。通过调试绑定,在运行标记扩展后,附加属性会获得正确的值,这似乎是一个计时问题。

有可能让它以某种方式工作吗?

4

2 回答 2

7

ProvideValue 方法被调用两次,一次是在解析器评估 XAML 时,一次是在加载值时。在第一次调用中,targetObject 只是一种称为 SharedDP 的虚拟对象,而不是应用标记扩展的对象。您需要跳过第一个电话,只处理第二个电话。这是在我们的应用程序中工作的代码。

   public override object ProvideValue(IServiceProvider serviceProvider){                                
                var pvt = serviceProvider as IProvideValueTarget;
                if (pvt == null)
                {
                    return null;
                }


                var frameworkElement = pvt.TargetObject as FrameworkElement;
                if (frameworkElement == null)
                {
                    return this;
                }
//.... Code will run once the markup is correctly loaded
 var dataContext = frameworkElement.DataContext; 


    }
于 2010-07-17T00:36:09.453 回答
1

也许,您可以从标记扩展将事件连接到页面上的 Loaded 或 Initialized 事件。或者,您可以在提到 Foo.Document 之后将您的标记扩展名放在 XAML 文件中。

谢谢, Rob Relyea WPF/XAML 团队 我的博客

于 2009-06-03T17:50:29.823 回答