在Silverlight 2中,我使用的是usercontrol,它继承了它嵌入的页面的datacontext。此datacontext包含问题文本,问题类型和答案集合。在用户控件中是一个列表框,它绑定到答案集合。如下图所示:
<ListBox DataContext="{Binding}" x:Name="AnswerListBox" ItemContainerStyle="{StaticResource QuestionStyle}" Grid.Row="1" Width="Auto" Grid.Column="2" ItemsSource="{Binding Path=AnswerList}" BorderBrush="{x:Null}" />
此列表框具有相关的样式,以单选按钮或复选框的形式显示答案(我想根据问题类型隐藏或显示):
<Style TargetType="ListBoxItem" x:Key="QuestionStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<StackPanel Background="Transparent" >
<RadioButton Visibility="{Binding Path=QuestionType, Converter={StaticResource QuestionTypeConverter}, ConverterParameter='RadioButtonStyle'}" Height="auto" Margin="0,0,0,10" IsChecked="{TemplateBinding IsSelected}" IsHitTestVisible="False" Content="{Binding Path=AnswerText}">
</RadioButton>
<CheckBox Visibility="{Binding Path=QuestionType, Converter={StaticResource QuestionTypeConverter}, ConverterParameter='CheckBoxStyle'}" Height="auto" Margin="0,0,0,10" Content="{Binding Path=AnswerText}">
</CheckBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
那么我的问题是:如何访问父数据上下文以获取QuestionType(因为这是用户控件datacontext本身的属性,而不是AnswerList中AnswerItem上的属性)?
或者,是否有更好的方法可以根据绑定值在xaml中动态切换样式?
答案 0 :(得分:55)
在Silverlight 3及更高版本中,您可以使用Element to Element绑定并指向控件DataContext,然后在我的示例中指向其Threshold属性中的某些属性。
首先命名你的控件(例如在我的例子中它的x:Name =“control”)
<UserControl x:Class="SomeApp.Views.MainPageView" x:Name="control" >
然后在ListBox ItemTemplate中的此控件内,您可以像这样访问父DataContext:
<ListBox ItemsSource="{Binding Path=SomeItems}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=control, Path=DataContext.Threshold}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
答案 1 :(得分:1)
我一直在与类似的问题作斗争。我的每个列表项都有一个组合框。顶级DataContext绑定到我的viewmodel(MVVM),如下所示:
class ViewModel{
ObservableCollection<ComboboxListItemType> DataForTheComboBoxList;
ObservableCollection<MyDataType> DataForTheListBox;
...
}
因为组合框位于列表框的ItemTemplate(= DataTemplate)中,所以每个列表项的DataContext都设置为DataForTheListBox中的相应项,组合框无法再从顶层DataContext中看到它需要的DataForTheComboBoxList。
我的(脏,丑)解决方法涉及在列表中的每个项目上设置完整的组合框列表,因此该列表项中的DataContext可以看到它。
首先,为列表框数据类型创建一个分部类。 (通常这将来自服务引用,因此您无法直接触摸生成的代码而不会丢失它)。此partial类包含一个引用组合框列表项类型的新属性:
public partial class MyDataType
{
private ObservableCollection<ComboboxListItemType> m_AllComboboxItems;
public ObservableCollection<ComboboxListItemType> AllComboboxItems
{
get { return m_AllComboboxItems; }
set
{
if (m_AllComboboxItems != value)
{
m_AllComboboxItems = value;
RaisePropertyChanged("AllComboboxItems");
}
}
}
}
接下来,您必须在DataForTheListBox集合中的每个元素上设置此属性
// in ViewModel class
foreach(var x in this.DataForTheListBox)
{
x.AllComboboxItems = this.DataForTheComboBoxList;
}
然后回到你的XAML:
<DataTemplate x:Key="ListBoxItemTemplate">
...
<Combobox
ItemsSource="{Binding AllComboboxItems}"
SelectedItem="{Binding CurrentBlah}"/>
</DataTemplate>
不要忘记,为了使组合框正确显示当前项目,所选项目必须引用组合框的ItemsSource中的实际项目。如果要从具有ID或对象的Web服务获取数据来表示组合框的项目,则必须重新引用它们以指向实际的集合。
答案 2 :(得分:1)
使用silverlight可以做的非常酷的事情是使用Tag属性来存储对其绑定的对象的引用。
首先,在你的班级中,声明一个像这样的属性
public IMyObject Current
{
get {return this;}
}
然后在控制中提升事件,你可以获得对象的引用
var fe= (FrameworkElement) sender;
var src = fe.Tag as IMyObject;
所以现在我有了这个对象,对象引用它的父对象是合理的,然后绑定到
Current.Parent.QuestionType
答案 3 :(得分:1)
如果您尝试使用DataForm执行此操作,则Robobloq显示的方法不起作用。