【问题标题】:silverlight - binding to two objectssilverlight - 绑定到两个对象
【发布时间】:2011-05-03 09:48:34
【问题描述】:

我想创建一个用户控件,它可以绑定到控件外部给出的一些数据(要求 A),并且一些 XAML 属性必须绑定到控件本身的属性(要求 B)。

假设我有一个名为 StudentData 的数据类和一个名为 StudentControl 的控件。我在 DataGrid 中使用这个控件。我将 StudentControl 放入带有 DataGridTemplateColumn 的网格中。我以某种方式将当前单元格中的 StudentData 绑定到控件。这是要求 A。此 StudentControl 想要指定其中的某些控件是否可编辑。最好的方法是公开一个属性,例如 StudentControl.AreSomeControlsEditable。然后我可以将这些控件的 IsEnabled 属性绑定到该属性。这是要求 B。

这是我的第一个想法。我将当前 StudentData 绑定到 StudentControl 的 DP,然后,在 StudentControl 内部,我将数据上下文更改为控件本身:

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <TextBox
    Content="{Binding Path=ExposedStudentData.Field1}" *reqA*
    IsEnabled="{Binding Path=OtherProperty1}" /> *reqB*
</UserControl>

这样,我想,StudentControl 从外部获取 StudentData,公开相同的 StudentData 和其他新属性(因此数据和其他属性现在在一个地方,而不是两个),然后我可以绑定到这些XAML 中公开的属性(同时满足 reqA+reqB)。除非这因为this bug 而不起作用。基本上,如果我将控件的 DataContext 设置为自身,那么它会在应用外部绑定之前设置。因此,如果我在单元格内的绑定路径是 X,然后数据上下文发生变化,则绑定引擎将在新的自身数据上下文中查找 X,而不是在外部网格数据上下文中。

这是我的第二个想法。我将当前的 StudentData 绑定到 DataContext 或 StudentControl 的 DP。然后,为了访问 StudentControl 的其他公开属性,我为 UserControl 命名并使用 ElementName 绑定:

<UserControl x:Name="self">
  <TextBox
    Content="{Binding Path=Field1}" *reqA*
    IsEnabled="{Binding ElementName=self, Path=OtherProperty1" /> *reqB*
</UserControl>

这样,我想,当前的数据上下文是 StudentData,它没有改变,我可以用一个简单的路径 (reqA) 绑定到它,我可以用 ElementName 东西绑定到其他公开的属性 (要求B)。由于this bug,它适用于基本场景,但不适用于DataGrid。我猜当视觉树中有多个具有相同名称的控件时会出现问题。

我真的开始讨厌 Silverlight,我一个月前开始使用它,我已经报告了 9 个错误。每当我尝试实现除了简单的 hello world 应用程序或 Microsoft 和其他所有人似乎都在使用 Silverlight 的东西之外的东西时,我都会遇到一个新错误。那么现在,您将如何绑定到从控件外部提供的数据类以及同时由控件公开的一些其他属性?当然,无需从代码设置绑定(其中我现在正在做,但它是 ListBoxes 和 DataTemplates 的噩梦)或根本不使用绑定。

【问题讨论】:

    标签: data-binding silverlight-4.0


    【解决方案1】:

    我认为您的问题在于 DataContext 及其继承方式,以及 namescopes

    首先,您应该知道,如果控件没有指定自己的 DataContext,它将继承其父级的 DataContext,并且对于 ItemsControl 派生控件,每个 Item 都将其 DataContext 设置为其中的一个数据项ItemsSource 集合。

    对于第二个问题,如果您在 DataTemplate 内部,那么您在与外部不同的名称范围内。您不能在 DataTemplate 之外“按名称”访问控件。您可以在此处(对于 Silverlight 4 及更低版本)执行的操作是自己遍历 Visual Tree 并查找所需的控件。但是,使用 SL5 中的一些新功能,特别是“FindAncestor”功能(WPF 中已经存在),这将变得更加容易和不那么痛苦。

    这是 MSDN 上关于 Namescopes in Silverlight 的文章。这是另一个关于 DataBinding 的内容,mentions how DataContext is inherited

    为了实现您的目标,我认为this blog post 应该可以帮助您。它向您展示了如何在 Silverlight 中实现类似“使用 FindAncestor 的相对源绑定”的行为。

    希望这会有所帮助:)

    【讨论】:

      【解决方案2】:

      在另一个论坛上,他们告诉我使用 MVVM。事实证明,它可以让我的第一个想法变得更好。与其将我的 StudentControl 绑定到 StudentData,然后公开这些数据和其他属性,不如创建一个视图模型,比如说 StudentControlData,它包含一个 StudentData 和控件所需的其他属性。如果我将我的控件绑定到这个,那么在控件的继承数据上下文中,我可以访问我需要的所有属性。现在剩下的唯一问题是在我的 StudentControl 的 ListBox 中,我丢失了这个数据上下文。

      【讨论】:

      • 就像我在上面的回答中所说的,我缺少的主要是 MVVM。但是对于我的列表框模板,我也需要这个。
      猜你喜欢
      • 2011-09-17
      • 2011-08-31
      • 1970-01-01
      • 2023-04-09
      • 2013-08-26
      • 2011-02-11
      • 1970-01-01
      • 1970-01-01
      • 2015-01-16
      相关资源
      最近更新 更多