Reputation: 356
I've got the following setup for my ListBox
in wpf:
ListBox
with as ItemsPanel
a StackPanel
(orientation horizontal)ItemTemplate
of ListBox
is a Grid
with a TextBox
and an ItemsControl
ItemPanel
a WrapPanel
.Somehow when I click on one of the buttons in the ItemsPanel
, the ICommand
wont fire in the ViewModel class which is bound to the View.xaml.
It looks like I'm selecting the ListBox
item and not the item within the ItemsControl
.
Here's the xaml code
<ListBox
Background="Transparent"
ItemTemplate="{StaticResource ProductGroupTemplate}"
FocusVisualStyle="{x:Null}"
VerticalContentAlignment="Top"
ItemsSource="{Binding NodeHeaders}"
Grid.Row="1"
Grid.ColumnSpan="3"
Grid.Column="0"
Grid.RowSpan="2"
SelectedItem="{Binding CurrentItem}"
BorderBrush="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
Margin="30,0,55,0"
VerticalAlignment="Top">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding HasParent}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
And the DataTemplate
<DataTemplate x:Key="ProductGroupTemplate">
<Grid Margin="0,0,20,0">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}" FontSize="20" Grid.Row="0" Grid.Column="0" Foreground="{StaticResource DefaultLabelColor}" />
<ItemsControl ItemsSource="{Binding Nodes}" Grid.Row="1" Grid.Column="0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Text="{Binding Description}" Height="75" Width="150" Padding="5" Margin="5" Background="{StaticResource SalesItemsBackground}"
Foreground="{StaticResource SalesItemsForeground}" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Left" Command="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type ContentControl}},
Path=DataContext.Select}" CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
Upvotes: 0
Views: 814
Reputation: 841
That's because your data template's DataContext is set to an item from the listbox. If you have List<Person> bound to your list box every list box item's DataContext would be a Person which is why you can write something like "{Binding Description}". You have two ways to execute a command from DataTemplate one of them is the one that "Sheridan" told you. As an alternative you could set your element's DataContext to your parent View or ViewModel.
<DataTemplate>
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type View/ViewModel}}">
</Grid>
</DataTemplate>
Upvotes: 0
Reputation: 69959
If you have a view model that declares an ICommand
instance and is set as the DataContext
of a view (UserControl
, or Window
), then you can use that property to access your ICommand
instance. From the Button
in your DataTemplate
, you can use this RelativeSource Binding
:
<Button Text="{Binding Description}" Height="75" Width="150" Padding="5" Margin="5"
Background="{StaticResource SalesItemsBackground}" TextAlignment="Left"
Foreground="{StaticResource SalesItemsForeground}" HorizontalAlignment="Center"
VerticalAlignment="Center" Command="{Binding DataContext.Select, RelativeSource={
RelativeSource AncestorType={x:Type YourViewsPrefix:YourView}}}"
CommandParameter="{Binding}"/>
Upvotes: 1