Привязка MVVM в Silverlight3 ItemsControl для получения родительских элементов управления DataContext - PullRequest
2 голосов
/ 01 апреля 2010

У меня есть следующий ItemsControl в Silverlight 3.

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

Проблема в том, что у меня есть ItemControl, привязанный к Коллекции в моей ViewModel, но мне нужна кнопка для запуска команды на ViewModel, которая, конечно, недоступна в DataContext кнопки, поскольку она содержит только коллекцию.

Я могу запустить команду, установив мой ViewModel в качестве ресурса и затем связав его с ним как StaticResource, но я хочу знать, почему привязка элемента к элементу не будет работать в этом сценарии. Я бы предпочел не использовать привязку StaticResource, потому что для этого требуется конструктор по умолчанию в ViewModel, и поэтому я не могу легко внедрить свои данные.

UPDATE

Я работаю над этим медленно ... Глядя на предложения Питера, я понял, что у меня могут быть более серьезные проблемы с привязкой из-за настройки моей страницы. У меня есть два возможных препятствия, но обо всем по порядку.

Элемент управления My Items выше обернут в другой элемент управления 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>

Еще раз спасибо всем за помощь!

Ответы [ 3 ]

3 голосов
/ 30 июня 2010

лучшее решение, которое я нашел до сих пор, чтобы справиться с этой ситуацией, - Дэн Уол, где он использует DataContextProxy.

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

1 голос
/ 07 апреля 2010

Попробуйте изменить
от

cmd: ButtonBaseExtensions.Command = "{Binding ElementName = LayoutRoot, Path = ButtonCommand}"

до

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

ИЛИ

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

0 голосов
/ 02 апреля 2010

В MVVM обмен сообщениями является сильной концепцией для связи между ViewModels. Вы можете использовать PRISM Eventaggregator или класс Messenger MVVM Light Toolkit. По команде кнопки вы можете опубликовать сообщение и подписаться на него в viewmodel.

...