【问题标题】:How do I access the datacontext of a silverlight control in the codebehind如何在代码隐藏中访问 silverlight 控件的数据上下文
【发布时间】:2010-11-11 11:32:22
【问题描述】:

我有一个 Silverlight 控件,我正在像这样实例化:

<MyControls:SomeControl DataContext="{Binding}" />

在这个文件的代码隐藏中,我怎样才能访问这个数据上下文? this.DataContext 等于 null。

编辑(更多信息):

我正在为现有的 silverlight 应用程序构建扩展。我与应用程序集成的观点如下:

<DataTemplate x:Key="AnImportantIdentifierUsedByTheHostApp">
    <MyControls:SomeControl DataContext="{Binding}" />
</DataTemplate>

在我的控件中,我可以绑定如下属性:

<Hyperlink NavigateUri="{Binding Path=UriWithSlug}">

这一切都很好。但是对于某些功能(具体来说,我需要使用 WebBrowser 控件和 NavigateToString() 方法),我需要从 DataContext 访问属性。

基本上在代码隐藏中,我需要做一些事情来达到以下效果:

myWebBrowser.NavigateToString(DataContext.MyHTMLStringProperty);

【问题讨论】:

    标签: silverlight


    【解决方案1】:

    您不需要DataContext={Binding},因为这相当于DataContext = DataContext

    但是,您缺少的是类型信息。绑定使用反射来解析属性路径,但是在代码隐藏中,您需要知道DataContext 返回的对象的类型。

    如果你能确定,那么它就是:-

    myWebBrowser.NavigateToString(((MyType)DataContext).MyHTMLString); 
    

    如果您无法确定类型和/或您无法说服控制您的控件主机的任何人确保至少实现了具有已知成员的特定接口,那么您可能需要自己进行反思.

    使用绑定系统为你做反射

    如果您不能只知道属性名称的类型,则另一种选择:-

    public string HTMLString
    {
       get { return (string)GetValue(HTMLStringProperty); }
       set { SetValue(HTMLStringProperty, value); }
    }
    public static DependencyProperty HTMLStringPropery =
       DependencyProperty.Register(
          "HTMLString",
          typeof(string),
          typeof(SomeControl),
          null);
    

    现在,如果您确定知道要绑定的属性的名称,则可以在控件构造函数的代码中设置绑定:-

    SetBinding(HTMLStringProperty, new Binding("MyHTMLString"));
    

    有了这个,你的代码看起来像:-

    myWebBrowser.NavigateToString(HTMLString);
    

    或者,您可以将控件的这个新属性绑定为 Xaml 的责任:-

    <DataTemplate x:Key="AnImportantIdentifierUsedByTheHostApp">                  
        <MyControls:SomeControl HTMLString="{Binding MyHTMLString}" />                  
    </DataTemplate> 
    

    【讨论】:

    • 好的,我已经删除了加载控件的 XAML 上的 DataContext={Binding},并且我知道 DataContext 的类型,但是我的问题仍然存在,在后面的代码中,DataContext是 == 空。 myWebBrowser.NavigateToString(((MyType)DataContext).MyHTMLString);抛出异常,因为 DataContext 为空。
    【解决方案2】:

    答案当然是超级直截了当,我敢肯定每个人都认为我在做的事情......

    在控件的Loaded 事件触发之前,DataContext 不可用。

    public MyUserControl() {
        var dc = this.DataContext // DataContext is null here in the ctor.
    
        this.Loaded += (s, e) => {
            var sc2 = this.DataContext // Loaded event fires, DataContext exists!
        };
    }
    

    再说一次,我确信这对许多 SL 开发者来说可能是显而易见的,但它完全让我感到困惑。

    【讨论】:

    • 感谢您发布此信息。不要感到孤独,我犯了同样的错误。现在,很明显 DataContext 在构造函数中将为空。
    【解决方案3】:

    好的,现在更有意义了。相应地改变答案...

    基本上,您永远不需要 DataContext={Binding}。项目的 DataContext 由父控件设置(按项目)。在从 ItemsSource 中的条目生成的大多数列表类型控件中。

    1. 能否删除 DataContext={Binding} 并检查它是否仍然有效?
    2. 如果实际子控件本身没有明确的 DataContext 值,那么要获取父控件的 DataContext,您可能必须向上导航可视化树(直到找到非 null DataContext)。

    您能否提供更多我们可以在上下文中看到的代码/xaml?

    【讨论】:

    • 其实DataContext属性应该返回当前的“非空DataContext”,它会为你搜索可视化树。
    • @AnthonyWJones:非常正确,但昨晚睡得很少,我不想这么说:)
    • @HiTech Magic,这几乎是所有代码,树上的任何内容都包含在我无法访问的主机应用程序中。我已经删除了 DataContext={Binding} 并且我的绑定仍然有效,但是 DataContext 在后面的代码中仍然为空。
    • @DaRKoN_:DataTemplate 在什么容器类型中?
    • @HiTech Magic,一个资源字典
    【解决方案4】:
    var mytype = this.DataContext as MyType;
    

    作为预防措施,我会在之后检查 null:

    if (mytype!=null)
    {
        // do something here
        myWebBrowser.NavigateToString(mytype.MyHTMLStringProperty);
    }
    

    【讨论】:

    • this.DataContext 始终为空!那是我的问题!
    猜你喜欢
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多