Reputation: 183
I made UWP app with MVVM pattern(i think so :) ) My app have data template for listbox. ListBox in View.xaml:
<ListBox x:Name="lbMySongs" ItemsSource="{Binding Path=MySongs}" ItemTemplate="{StaticResource lbSongsTemplate}" Grid.Row="1">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox/>
DateTemplate resource:
<DataTemplate x:Key="lbSongsTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Artist}" Grid.Column="0"/>
<TextBlock Text=" - " Grid.Column="1"/>
<TextBlock Text="{Binding Path=Title}" Grid.Column="2"/>
//Here i bind command, but it's not binding cos ItemsSource have no command. ViewModel have this command.
<Button Command="{Binding Path=DownloadCommand}" Content="{Binding Path=Query}"/>
<TextBlock Text="{Binding Duration}" Grid.Column="5" HorizontalAlignment="Right"/>
</Grid>
</DataTemplate>
Need to set DataContext for this button. My command in ViewModel. Example:
class ViewModel
{
...
public RelayCommand DownloadCommand { get; set; }
public ObservableCollection<SomeClass> MySongs { get; set; }
...
}
My problem: DataTemplate have ItemsSource = ViewModel.MySongs. But "DownloadCommand" is in ViewModel. What i type in DataTemplate for my button set binding to DownloadCommand?
Upvotes: 1
Views: 5305
Reputation: 132548
Use a RelativeSource
binding to say you want to bind to ListBox.DataContext.DownloadCommand
<Button Command="{Binding Path=DataContext.DownloadCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
Content="{Binding Path=Query}"/>
Its often common practice like this to also bind the CommandParameter
to the item to know what item the command was executed on :
<Button Command="{Binding Path=DataContext.DownloadCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
CommandParameter="{Binding }"
Content="{Binding Path=Query}" />
You could also use an ElementName
binding, but then you have to give your ListBox
a Name to specify in your DataTemplate, and I don't personally like to hardcode ElementName
in my DataTemplates. Makes it annoying to find and fix if you change something's name, or want to use the DataTemplate in another ListBox.
Upvotes: 3
Reputation: 4306
Try to use:
<Button Command="{Binding Path=DataContext.DownloadCommand, ElementName=lbMySongs}"
CommandParameter="{Binding}"
Content="{Binding Path=Query}"/>
And change
public RelayCommand DownloadCommand { get; set; }
to
public RelayCommand<SomeClass> DownloadCommand { get; set; }
...
DownloadCommand = new RelayCommand<SomeClass>(DownloadExecute);
...
private voir DownloadExecute(SomeClass item)
{
...
}
Upvotes: 3