WPF Binding to an Object in a Collection

Marc Jeeves 121 Reputation points
2021-12-16T21:15:12.253+00:00

Afternoon, I have a grid of images with a left click gesture, I have created a command and bound to it which fires, but I want to send the related object (the viewmodel that contains the image and other data) from my collection to the command.

The UI shows and the images all work, I am correctly bound to my view model.

What do I bind to for my command parameter on line .17?

thanks

Madaxe

    <Window.Resources>

        <DataTemplate x:Key="ItemTemplate">
            <WrapPanel>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="auto"/>
                    </Grid.RowDefinitions>
                    <Image x:Name="ButtonImage" Grid.Row="0" 
                           Width="35" Height="35" 
                           Stretch="Fill" 
                           Source="{Binding Bitmap_Source}">
                        <Image.InputBindings>
                            <MouseBinding Gesture="LeftClick" 
                                          Command="{Binding TestCommand, Mode=OneTime}"
                                          **CommandParameter="{Binding }"/>**
                        </Image.InputBindings>
                    </Image>
                    <TextBlock Grid.Row="1" 
                               Text="{Binding Name}"/>
                </Grid>
            </WrapPanel>
        </DataTemplate>
    </Window.Resources>

    <Grid Background="#D1D4D4">
        <TabControl Background="#F1F1F1">
            <TabItem Header="Nikola Apps" Background="#F1F1F1">
                <StackPanel Background="#F1F1F1" Orientation="Vertical">
                    <Button x:Name="Temp" Content="Hide/Show" Height="25" Width="100" Click="Temp_Click"/>
                    <Expander Header="Apps" VerticalAlignment="Top" HorizontalAlignment="Stretch">

                        <Grid x:Name="movie_grid" Background="#FFE5E5E5">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                            </Grid.RowDefinitions>

                            <ListView Grid.Row="0" Background="#FFE5E5E5"
                                Name="MovieListView"
                                ItemTemplate="{StaticResource ItemTemplate}"
                                ItemsSource="{Binding Path=CATIAAppsCollectionViewModel.CATIAApps}">
                                <ListView.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <UniformGrid Columns="3" />
                                    </ItemsPanelTemplate>
                                </ListView.ItemsPanel>
                            </ListView>
                        </Grid>
                    </Expander>
                    <Button x:Name="Close" Content="Close" Height="25" Width="100" Click="Close_Click"/>
                </StackPanel>
            </TabItem>
        </TabControl>
    </Grid>
</Window>
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,686 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2021-12-17T08:37:47.377+00:00

    Hi Marc,
    try following demo with your a litte changed code:

    XAML:

    <Window x:Class="WpfApp1.Window091"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp091"  
            mc:Ignorable="d"  
            Title="MarcJeeves-1751_211712" Height="450" Width="800" Top="100">  
      <Window.Resources>  
        <local:CATIAAppsCollectionViewModel x:Key="vm"/>  
        <DataTemplate x:Key="ItemTemplate">  
          <WrapPanel>  
            <Grid>  
              <Grid.RowDefinitions>  
                <RowDefinition Height="auto"/>  
                <RowDefinition Height="auto"/>  
              </Grid.RowDefinitions>  
              <Image Grid.Row="0"   
                     Width="35"   
                     Height="35"   
                     Stretch="Fill"   
                     Source="{Binding Bitmap_Source}">  
                <Image.InputBindings>  
                  <MouseBinding Gesture="LeftClick"   
                                Command="{Binding Cmd, Source={StaticResource vm}}"  
                                CommandParameter="{Binding}"/>  
                </Image.InputBindings>  
              </Image>  
              <TextBlock Grid.Row="1" Text="{Binding Name}"/>  
            </Grid>  
          </WrapPanel>  
        </DataTemplate>  
      </Window.Resources>  
      
      <Grid Background="#D1D4D4" DataContext="{StaticResource vm}">  
        <TabControl Background="#F1F1F1">  
          <TabItem Header="Nikola Apps" Background="#F1F1F1">  
            <StackPanel Background="#F1F1F1" Orientation="Vertical">  
              <Button x:Name="Temp"   
                      Content="Hide/Show"   
                      Height="25"   
                      Width="100"  
                      Command="{Binding Cmd}"  
                      CommandParameter="Temp_Click"/>  
              <Expander Header="Apps"   
                        VerticalAlignment="Top"   
                        HorizontalAlignment="Stretch"  
                        IsExpanded="{Binding AppsExpanded}"  
                        Visibility="{Binding Hide_Show}">  
                <Grid Background="#FFE5E5E5">  
                  <Grid.RowDefinitions>  
                    <RowDefinition Height="auto"/>  
                  </Grid.RowDefinitions>  
                  <ListView Grid.Row="0"   
                            Background="#FFE5E5E5"  
                            ItemTemplate="{StaticResource ItemTemplate}"  
                            ItemsSource="{Binding CATIAApps}">  
                    <ListView.ItemsPanel>  
                      <ItemsPanelTemplate>  
                        <UniformGrid Columns="3" />  
                      </ItemsPanelTemplate>  
                    </ListView.ItemsPanel>  
                  </ListView>  
                </Grid>  
              </Expander>  
              <Button x:Name="Close"   
                      Content="Close"   
                      Height="25"   
                      Width="100"   
                      Command="{Binding Cmd}"  
                      CommandParameter="Close_Click"/>  
            </StackPanel>  
          </TabItem>  
        </TabControl>  
      </Grid>  
    </Window>  
    

    and classes:

    using System;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
    using System.Windows;  
    using System.Windows.Data;  
    using System.Windows.Input;  
    using System.Windows.Media;  
    using System.Windows.Media.Imaging;  
      
    namespace WpfApp091  
    {  
      class CATIAAppsCollectionViewModel : INotifyPropertyChanged  
      {  
        public CATIAAppsCollectionViewModel() => cvs.Source = GetData();  
      
        private ObservableCollection<Data> GetData()  
        {  
          ObservableCollection<Data> col = new ObservableCollection<Data>();  
          string[] pathes = { "Cube_1", "Cube_2", "Cube_3", "Cube_4", "Cube_5", "Cube_6" };  
          for (int i = 0; i <= pathes.GetUpperBound(0); i++)  
          {  
            BitmapImage imgSource = new BitmapImage();  
            string texturePath = $"./Pictures/{pathes[i]}.PNG";  
            imgSource.BeginInit();  
            imgSource.UriSource = new Uri(texturePath, UriKind.Relative);  
            imgSource.EndInit();  
            col.Add(new Data() { Name = $"Picture {i + 1}", Bitmap_Source = imgSource });  
          }  
          return col;  
        }  
      
        private CollectionViewSource cvs = new CollectionViewSource();  
        public object CATIAApps { get => cvs.View; }  
        public ICommand Cmd { get => new RelayCommand(CmdExec); }  
        private void CmdExec(object obj)  
        {  
          switch (obj.ToString())  
          {  
            case "Temp_Click":  
              Hide_Show = (Hide_Show == Visibility.Visible) ? Visibility.Hidden : Visibility.Visible;  
              OnPropertyChanged(nameof(Hide_Show));  
              break;  
            case "Close_Click":  
              AppsExpanded = false;  
              OnPropertyChanged(nameof(AppsExpanded));  
              break;  
            default:  
              if (obj is Data) MessageBox.Show($"{((Data)obj).Name} is clicked");  
              break;  
          }  
      
        }  
        public bool AppsExpanded { get; set; } = false;  
        public Visibility Hide_Show { get; set; } = Visibility.Visible;  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
      
      }  
      
      public class Data  
      {  
        public string Name { get; set; }  
        public ImageSource Bitmap_Source { get; set; }  
      }  
      
      public class RelayCommand : ICommand  
      {  
        private readonly Action<object> _execute;  
        private readonly Predicate<object> _canExecute;  
        public RelayCommand(Action<object> execute) : this(execute, canExecute: null) { }  
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)  
        {  
          if (execute == null) throw new ArgumentNullException("execute");  
          this._execute = execute;  
          this._canExecute = canExecute;  
        }  
        public event EventHandler CanExecuteChanged;  
        public bool CanExecute(object parameter) => this._canExecute == null ? true : this._canExecute(parameter);  
        public void Execute(object parameter) => this._execute(parameter);  
        public void RaiseCanExecuteChanged() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);  
      }  
    }  
    

    Result:

    158561-x.gif

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Marc Jeeves 121 Reputation points
    2021-12-16T21:21:23.763+00:00

    CommandParameter="{Binding BindsDirectlyToSource=True}"/>

    this gives mewhat i want