我在 Silverlight 3 中有以下 ItemsControl。
<ItemsControl ItemsSource="{Binding ValueCollectionList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="MyBtn" Height="40" Content="{Binding Name}"
Tag="{Binding Value}"
cmd:ButtonBaseExtensions.Command="{Binding ElementName=LayoutRoot, Path=ButtonCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding ElementName=MyBtn, Path=Tag}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
问题是我将 ItemsControl 绑定(bind)到 ViewModel 中的 Collection,但我需要按钮来触发 ViewModel 上的命令,这当然在按钮的 DataContext 中不可用,因为它只包含集合。
我可以通过将 ViewModel 设置为资源,然后将其绑定(bind)为 StaticResource 来触发命令,但我想知道为什么元素到元素的绑定(bind)在这种情况下不起作用。我不想使用 StaticResource 绑定(bind),因为这需要 ViewModel 上的默认构造函数,因此我无法轻松注入(inject)数据。
更新
我正在慢慢解决这个问题...查看 Peter 的建议,我意识到由于我的页面设置,我可能会遇到更严重的绑定(bind)问题。我有两个可能的障碍,但首先要做的是。
上面的“我的项目”控件包装在另一个绑定(bind)到可观察集合的项目控件中。我移动了项目控件,使其成为根项目控件的直接子级。它被包裹在我将要讨论的另一个控件中。因此,我尝试将元素绑定(bind)到项目控件 ControlItemList,但它是一个集合,因此无法在该集合中找到我的 ButtonCommand 方法。我需要做的是绑定(bind)到该集合中的一个项目。如何绑定(bind)到集合中的单个项目?
<Grid x:Name="LayoutRoot" Background="White"><!-- DataContext="{Binding Path=., Source={StaticResource lvvm}}">-->
<StackPanel Orientation="Vertical">
<ItemsControl x:Name="ControlItemList" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="ControlName" Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center" />
<ItemsControl ItemsSource="{Binding ValueCollectionList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
因此,假设我可以使上述内容正常工作,另一个障碍是我的项目控件包装在我用来获取 DataTemplateSelector 类型功能的另一个用户控件中。我认为这个控件可能会阻止我访问父 DataContext。您可以爬到树上多远有限制吗?
<common:DeviceControlTemplateSelector Grid.Column="1" FieldType="{Binding ValueType}" Margin="0,2,0,2">
<common:DeviceControlTemplateSelector.StringTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, Mode=TwoWay}" Width="100"/>
</DataTemplate>
</common:DeviceControlTemplateSelector.StringTemplate>
<common:DeviceControlTemplateSelector.DateTimeTemplate>
<DataTemplate>
<TextBox Text="this is date time binding" Width="100"/>
</DataTemplate>
</common:DeviceControlTemplateSelector.DateTimeTemplate>
<common:DeviceControlTemplateSelector.BooleanTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Value, Mode=TwoWay}" />
</DataTemplate>
</common:DeviceControlTemplateSelector.BooleanTemplate>
<common:DeviceControlTemplateSelector.IntegerTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ValueCollection}" DisplayMemberPath="Value" SelectedIndex="{Binding Value, Mode=TwoWay}" >
</ComboBox>
</DataTemplate>
</common:DeviceControlTemplateSelector.IntegerTemplate>
<common:DeviceControlTemplateSelector.MultiButtonTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding ValueCollectionList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button x:Name="MyBtn"
Height="40" Content="{Binding Name}"
Tag="{Binding Value}"
cmd:ButtonBaseExtensions.Command="{Binding ElementName=ControlItemList, Path=DataContext.ButtonCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding Value}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</common:DeviceControlTemplateSelector.MultiButtonTemplate>
<Button x:Name="MyBtn"
Height="40" Content="{Binding Name}"
Tag="{Binding Value}"
cmd:ButtonBaseExtensions.Command="{Binding ElementName=ControlItemList, Path=ButtonCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding Value}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
再次感谢大家的帮助!
最佳答案
到目前为止,我找到的处理这种情况的最佳解决方案是 Dan Wahl 提出的,他使用了 DataContextProxy。
关于silverlight - Silverlight3中MVVM绑定(bind)ItemsControl获取父控件DataContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2562925/