MVVM在Silverlight3的ItemsControl绑定获取父控件的DataContext

MVVM在Silverlight3的ItemsControl绑定获取父控件的DataContext

问题描述:

在Silverlight中,我有以下的ItemsControl 3MVVM在Silverlight3的ItemsControl绑定获取父控件的DataContext

<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> 

的问题是,我有绑定到收藏在我的ViewModel ItemsControl的,但我需要的按钮在ViewModel上触发一个当然不是按钮的DataContext中可用的命令,因为它只包含集合。

我可以通过设置我的ViewModel作为资源,然后绑定到一个StaticResource,但我想知道为什么元素绑定元素不能在这种情况下工作。我宁愿不使用StaticResource绑定,因为这需要ViewModel上的默认构造函数,所以我无法轻松注入数据。

UPDATE

我通过这个速度很慢......望着彼得,我意识到,我可能因为我的页面设置的更严重的绑定问题的建议。我有两个可能的路障,但首先是第一件事。

上面的My Items控件包含在另一个绑定到可观察集合的项目控件中。我移动了我的项目控件,以便它的根项目控件的直接子项。它被包裹在另一个控制中,我会到达。所以我尝试了绑定到项目控件ControlItemList的元素,但是它是一个集合,所以它无法在该集合中找到我的ButtonCommand方法。我需要做的是绑定到该集合中的一个项目。如何绑定到集合中的单个项目?

<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> 

再次感谢大家的帮助!

在MVVM消息传递中,ViewModels之间的通信是一个强大的概念。您可以使用PRISM Eventaggregator或MVVM Light Toolkit的Messenger类。在按钮命令上,您可以发布消息并在视图模型中订阅它。

+0

谢谢silverfighter的职位,但我真的想知道为什么我上面的代码不起作用。我可能不得不去消息路由或使ViewModel一个静态资源,但我不明白为什么我不能从我的itemscontrol内访问父对象datacontext。 – BigTundra 2010-04-06 12:52:52

+0

EventAggregator在单个ViewModel中的消息传递是否过度(更不用说Module)了? – Pat 2011-01-21 18:08:13

尝试从

CMD改变
:ButtonBaseExtensions.Command = “{结合的ElementName = LayoutRoot,路径= ButtonCommand}”

CMD:ButtonBaseExtensions.Command =“{结合的ElementName = LayoutRoot,路径= DataContext.ButtonCommand}”

OR

cmd:ButtonBaseExtensions.Command =“{Binding ElementName = LayoutRoot.DataContext,Path = ButtonCommand}”

+0

我无法得到这个工作,因为LayoutRoot的DataContext是一个ObservableCollection,所以当我尝试绑定到我的ButtonCommand方法时,我得到... System.Windows.Data错误:BindingExpression路径错误:'ButtonCommand' 'System.Collections.ObjectModel.ObservableCollection'1 [Chopper.Common.DeviceControlViewModel]''System.Collections.ObjectModel.ObservableCollection'1 [Chopper.Common.DeviceControlViewModel]'(HashCode = 26753075)上找不到属性。 BindingExpression:Path ='DataContext.ButtonCommand'DataItem ='System.Windows.Controls.ItemsControl' 如何绑定到该项目? – BigTundra 2010-04-13 13:45:36

我发现迄今为止处理这种情况的最佳解决方案是由Dan Wahl在哪里使用DataContextProxy。

http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx