0

I have a ListBox that looks like this:

<ListBox Name="ListBoxUsers" ItemsSource="{Binding Path=TempObservableUsers, ElementName=MainWindow, NotifyOnSourceUpdated=True}" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden" />

This ListBox shows, as you can see, a list of users comming from an ObservableCollection called TempObservableUsers. This part works fine.

Each element of the list looks like this:

enter image description here

As you can see, I modified my ItempsPanelTemplate to look differently. Here I attach my code:

 <Style TargetType="ListBox" x:Key="VerticalListBox">
    <Setter Property="Margin" Value="0,0,10,0"></Setter>
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="VerticalContentAlignment" Value="Top" />
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="BorderBrush" Value="{DynamicResource RegularBlue}" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="Width" Value="450" />
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical" Width="450" />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Orientation="Vertical" Width="450" Margin="0,5" >
                    <StackPanel Orientation="Horizontal" Background="{DynamicResource TransparentMainBlue}" >
                        <Image Width="70" Height="70" Margin="5" Source="../images/delete.png" />
                        <StackPanel Orientation="Vertical" Width="285" >
                            <StackPanel Orientation="Horizontal">
                                <Label Content="NAME:" FontWeight="Bold"/>
                                <Label Content="{Binding Path=Name, FallbackValue=Name}" Foreground="White" />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Content="ID:" FontWeight="Bold"/>
                                <Label Content="{Binding Path=Identifier, FallbackValue=Identifier}" />
                            </StackPanel>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Top">
                            <Image Source="../images/edit.png" Width="20" />
                            <Image Source="../images/detail.png" Width="20" />
                            <Image Source="../images/delete.png" Width="20" />
                        </StackPanel>
                    </StackPanel>
                    <Grid Height="30" Background="{DynamicResource RegularBlue}">
                        <Label Content="XXXX-XXXX-XXXX-XXXX" Foreground="White" HorizontalContentAlignment="Center" FontWeight="Bold" />
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Ok, after that:

As you can see, each item contains some images on top right corner. I want each one to do its job: edit, more, delete...

So I need to bind each image click with the corresponding item on the ListBox.

How can I bind each image click to do the corresponding action (edit, update, delete) and with its corresponding item on the ListBox?

EDIT: Now my code looks like this for each item template:

<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Top">
      <Button Command="{Binding DataContext.DeleteCommand}" CommandTarget="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}" CommandParameter="{Binding}">
          <Image Source="../images/delete.png" Width="20" />
      </Button>
      ............
 </StackPanel>

How to implement DeleteCommand? PS: I'm not using MVVM pattern yet, as I'm not famliar to it. Only trying to bind that button commands i xaml directly from my ResourceDictionary.

Sonhja
  • 8,230
  • 20
  • 73
  • 131

2 Answers2

1

If I were attempting to fulfil your requirements, then I would use Buttons with an Image inside instead of Images on their own. Next, I would use a form of RelayCommand to handle my ICommands in the view model. Using this method, passing the relevant item along to the ICommand is easy using the CommandParameter property:

<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" 
    VerticalAlignment="Top">
    <Button Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource
        AncestorType={x:Type YourPrefix:ThisView}}}" CommandParameter="{Binding}">
        <Image Source="../images/edit.png" Width="20" />
    </Button>
    <Button Command="{Binding DataContext.DetailCommand, RelativeSource={RelativeSource
        AncestorType={x:Type YourPrefix:ThisView}}}" CommandParameter="{Binding}">
        <Image Source="../images/detail.png" Width="20" />
    </Button>
    <Button Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource
        AncestorType={x:Type YourPrefix:ThisView}}}" CommandParameter="{Binding}">
        <Image Source="../images/delete.png" Width="20" />
    </Button>
</StackPanel>

In order for this to work, it presumes:

1) You have set the DataContext of your Window or UserControl to an instance of a class that has ICommand properties named EditCommand, DetailCommand and DeleteCommand.

2) You replace the XAML Namespace Prefix value of YourPrefix to your own valid prefix.

3) You replace the imaginary ThisView name of the view where this code will reside with the actual name of the Window or UserControl where you add this code, eg. MainWindow.

As for how to use RelayCommands, that is another question and goes against the single question, single problem ethos of Stack Overflow. However, there are many tutorials on this. Here are some to help you on your way:

  1. If you've not used ICommands before, then the Commanding Overview page on MSDN is an invaluable resource and a good introduction to them.
  2. You'll find dozens of useful posts by searching Stack Overflow for RelayCommand.
  3. You can find a clear implementation of this class in the Implementation RelayCommand question on the Visual Studio Forum.
Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Doesn't this layout suggest that Parameter is the same object that has the commands? You don't need it then. – icebat Jun 11 '14 at 15:22
  • @Sheridan Sounds interesting. I'm changing my images to buttons (true, it will be better than using an image). So, how to achieve that `EditCommand`, `DetailCommand` and so? Where and how to implement it? – Sonhja Jun 11 '14 at 15:23
  • @icebat, yes you're quite right... thanks for pointing that out. I'll edit my answer accordingly. – Sheridan Jun 11 '14 at 15:32
  • @Sheridan I could finally implement it! thanks a lot for your information! :)) – Sonhja Jun 12 '14 at 11:13
1

Since there is no command binding available for Image, I'll demo same using a Button appearing as in image

Start by writing a style for a button, to remove the original appearance and leave with only what i want to show ( image in this case)

<Style x:Key="simpleButton" TargetType="Button">
    <Setter Property="Width" Value="70"/>
    <Setter Property="Height" Value="70"/>
    <Setter Property="Margin" Value="5"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentPresenter/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Then I'll define my datatemplate as

<DataTemplate>
    <StackPanel Orientation="Vertical" Width="450" Margin="0,5" >
        <StackPanel Orientation="Horizontal" Background="{DynamicResource TransparentMainBlue}" >
            <Button Style="{StaticResource simpleButton}" 
                    Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=LixtBox}}" 
                    CommandParameter="{Binding}">
                <Image Source="../images/delete.png"/>
            </Button>
            ...

then I'll write a DeleteCommand in my view model an initialize it's implementation using SimpleCommand, RelayCommand etc.

public ICommand DeleteCommand { get; set; }

once this is all in place my button which is now showing an image will bind itself to the command and will push the current item as command parameter upon execution (which is click for button)

pushpraj
  • 13,458
  • 3
  • 33
  • 50
  • Great! I'm changing to Buttons. Now I'm trying to figure out how to implement that `DeleteCommand` and others! – Sonhja Jun 11 '14 at 15:33
  • you may refer to this topic about implementing relay command in wpf http://stackoverflow.com/questions/862570/how-can-i-use-the-relaycommand-in-wpf – pushpraj Jun 11 '14 at 15:45