我想创建一个用户控件,它可以绑定到从控件外部给出的一些数据(需求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的东西绑定到其他暴露的属性( REQB)。由于this bug,它适用于基本方案,但不适用于DataGrid。我猜测当可视树中有多个具有相同名称的控件时会出现问题。
我真的开始讨厌Silverlight,我一个月前开始使用它,我已经报告了9个bug。每当我尝试除了一个简单的hello world应用程序或者其他人似乎都在使用Silverlight之类的东西之外,我会遇到一个新的bug。那么现在,如何绑定到控件外部给出的数据类以及控件同时暴露的其他一些属性?当然没有设置代码绑定(其中我现在正在做,但这是ListBoxes和DataTemplates的噩梦)或根本不使用绑定。
答案 0 :(得分:1)
我认为您的问题在于DataContext及其继承方式,以及 namescopes 。
对于第一个,你应该知道如果一个控件没有指定它自己的DataContext,它将继承它的父控件,而对于ItemsControl派生控件,每个Item都将其DataContext设置为其中一个数据项。 ItemsSource集合。
对于您的第二个问题,如果您在DataTemplate中,那么您的名称范围与其他名称范围不同。您无法在DataTemplate之外“按名称”访问控件。你可以在这里做什么(对于Silverlight 4及以下版本)是自己遍历Visual Tree并寻找你想要的控件。然而,SL5中的一些新功能,特别是“FindAncestor”功能(已经存在于WPF中),这将变得更加容易和痛苦。
以下是有关Namescopes in Silverlight的MSDN文章。这是关于DataBinding的另一个mentions how DataContext is inherited。
为了实现您的目标,我认为this blog post可以为您提供帮助。它向您展示了如何在Silverlight中实现“与FindAncestor一样的RelativeSource绑定”行为。
希望这会有所帮助:)
答案 1 :(得分:0)
在另一个论坛上,他们告诉我使用MVVM。事实证明,它可以使我的第一个想法更好一些。我不应该将StudentControl绑定到StudentData,然后公开这些数据和其他属性,而应该创建一个viewmodel,比如说StudentControlData,它包含一个StudentData和控件所需的其他属性。如果我将控件绑定到此,那么在控件的继承数据上下文中,我可以访问所需的所有属性。现在唯一的问题是,在StudentControl的ListBox中,我丢失了这个数据上下文。