NZJames
NZJames

Reputation: 5055

WPF hyperlink in datatemplate listboxitem

I have a data template in WPF that is attached to a ResultsViewModel class and renders the VM in a table format. A bunch of these make up ListBoxItems in a ListBox. What I want is in each individual table to have a little X at the top right of the border where if you click it, it calls a function that removes that item from the listbox.

I have tried with a Hyperlink and event OnClick but then I have to have the DataTemplate in the main XAML and not in a resource dictionary as it needs a x:Class tag to use events, but then the event gets fired in the MainViewModel, which isn't the worst thing in the world as the observable list is held in the MainViewModel and needs to be removed at that point anyway, but I can't figure out how to get a reference to the ResultsViewModel of the list box item that contained the data template that was clicked

<DataTemplate x:Key="ErroredResultsTemplate" DataType="x:Type vm:ResultsViewModel" >
        <Border x:Name="Border" BorderBrush="{StaticResource ResultProcessedBorder}" Background="{StaticResource ResultFill}" BorderThickness="4" CornerRadius="10" Margin="6" Padding="5" Width="110" Height="110">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20" />
                    <RowDefinition Height="83" />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Foreground="{StaticResource ResultGrayText}" FontWeight="Bold" HorizontalAlignment="Right" VerticalAlignment="Top">
                <Hyperlink Click="Close_Results">X</Hyperlink>
                </TextBlock>
                <TextBlock Width="90" Text="An error occurred calculating results" TextWrapping="Wrap" Foreground="{StaticResource ResultGrayText}" FontWeight="Bold" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" TextAlignment="Center" />
            </Grid>
        </Border>
    </DataTemplate>

Upvotes: 0

Views: 1176

Answers (1)

Sheridan
Sheridan

Reputation: 69979

You can achieve this in two ways:

  1. Create a property of type ResultsViewModel in your parent view model (that contains your collection of ResultsViewModel objects) and bind that to the SelectedItem property of your ListBox. Add some kind of RelayCommand to the parent view model to handle the delete action, add a Button to your DataTemplate and bind its Command property to the new command. Then, when any delete button is clicked, you can just remove the item found in the SelectedItem property from your collection and the UI should update accordingly (assuming that you've implemented the INotifyPropertyChange interface).

  2. You can simply bind from the DataTemplate of each item in the ListBox to the parent view model directly. This assumes that you have a Command in your parent view model named Delete and that the parent view model is bound to the DataContext property of the Window or UserControl that the ListBox appears in. Also note the important CommandParameter="{Binding}" part which passes the data object from each item in the collection to the object parameter in the Command when a Command is called.

Example:

<Button Content="X" Command="{Binding DataContext.Delete, 
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type 
    XmlNameSpace:WindowOrUserControlName}}, Mode=OneWay}" 
    CommandParameter="{Binding}" />

Upvotes: 1

Related Questions