WPF ItemsControl can't bind Command

Carolina Gritti 41 Reputation points
2021-09-07T16:05:46.073+00:00

Hi All,

i'm a newbie in wpf and i know that this question has been asked other times, but i can't find a solution. I'm doing something wrong but i can't see what it is.

I have this Model

public class MyElement
{
        public string Text { get; set; }
        public string Image { get; set; }
        public int Index { get; set; }
        public MyElement(string t, string i, int id)
        {
            Text = t;
            Image = i;
            Index = id;
        }
  }

This Command

public class MyCommand: ICommand
        {
            public bool CanExecute(object parameter)
            { 
                return true; 
            }
            public event EventHandler CanExecuteChanged;
            public void Execute(object parameter)
            { 
                _handler(parameter);
            }

            private Action<object> _handler;
            public MyCommand(Action<object> handler) { _handler = handler; }
        }

This Model view

 public class MyItemsControlViewModel
    {
        ObservableCollection<BurgetMenuItem> _items;
        public ObservableCollection<BurgetMenuItem> BurgerItems { get { return _items; } set { _items = value; RaisePropertyChanged("BurgerItems"); } }
        ObservableCollection<BurgetMenuItem> _temporayList;
        private ICommand _itemClicked;
        public ICommand ItemClicked { get { return _itemClicked; } }

        public MyItemsControlViewModel()
        {
            _items = new ObservableCollection<BurgetMenuItem>();
            _temporayList = new ObservableCollection<BurgetMenuItem>();
            _itemClicked = new RelayC(OnItemSelected);
        }

        public void UpdateList()
        {
            _items = _temporayList;
        }
        public void AddItem(string t, string img, int id)
        {
            BurgetMenuItem item = new BurgetMenuItem(t, img, id);
            _temporayList.Add(item);
        }

        public void OnItemSelected(object param)
        {
            //
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

And this XAML

<UserControl x:Class="MyLibrary.MyCustomControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MyLibrary"
             mc:Ignorable="d" 
             d:DesignHeight="1080" d:DesignWidth="570"
             x:Name="myCustomControl">
    <Grid >
        <Image
            Width="570"
            Height="1080"
            Source="{Binding ElementName=myCustomControl, Path=ImageBack, Converter={StaticResource nullImageConverter}}">
        </Image>

        <Button Width="100" Height="100 " VerticalAlignment="Top" Command="{Binding ItemClicked}" />

        <ItemsControl 
                x:Name="listItems"             
                ScrollViewer.PanningMode="None"
                IsEnabled="False"
                Background = "Transparent"
                BorderThickness="0"
                ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                ScrollViewer.VerticalScrollBarVisibility="Disabled"               
                Margin="0,252,0,10"
                HorizontalAlignment="Left">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel HorizontalAlignment="Left" Margin="50,0,0,0" Background="Transparent" Orientation="Vertical"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                <DataTemplate>                  
                    <Button
                       Command="{Binding ElementName=myCustomControl, Path=DataContext.ItemClicked}">

                        <Grid Margin="0,60,0,0"
                        Background="Transparent">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="120"/>
                            <ColumnDefinition Width="3*"/>
                        </Grid.ColumnDefinitions>
                        <Image
                            Grid.Column="0"
                            Stretch="None"
                            Source="{Binding Image}"
                            Margin="0,0,40,0"
                            />
                        <Label 
                            Foreground="DimGray"
                            Grid.Column="1"
                            HorizontalAlignment="Left"
                            HorizontalContentAlignment="Left"
                            VerticalContentAlignment="Center"
                            FontSize="28"
                            Style="{StaticResource BoldLabel}"
                            Content="{Binding Text}"
                            TouchDown="Element_Click"/>
                    </Grid>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>

    </Grid>
</UserControl>

When i click on the button that is outside the ItemsControl, it works. I can execute the function OnMyItemSelected.

But when i click on one of the button that are in the ItemsControl, it doesn't work.
I try this

<Button
Command="{Binding ElementName=listItems, Path=DataContext.ItemClicked}">

And also this

<Button
Command="{Binding DataContext.ItemClicked, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ItemsControl}}">

Please help! And sorry if i'm doing something stupid!

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,709 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
789 questions
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,311 Reputation points
    2021-09-09T04:24:04.463+00:00

    Hi Carolina,
    your code work if you set Enabled to True:

     <UserControl x:Class="MyLibrary.MyCustomControl"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                  xmlns:local="clr-namespace:MyLibrary"
                  mc:Ignorable="d" 
                  d:DesignHeight="1080" d:DesignWidth="570"
                  x:Name="myCustomControl">
         <Grid >
             <Image
                 Width="570"
                 Height="1080"
                 Source="{Binding ElementName=myCustomControl, Path=ImageBack, Converter={StaticResource nullImageConverter}}">
             </Image>
    
         <Button Width="100" Height="100 " VerticalAlignment="Top" Command="{Binding ItemClicked}" />
    
         <ItemsControl 
                 x:Name="listItems"             
                 ScrollViewer.PanningMode="None"
                 IsEnabled="True"   <- ----------------------------------------------!!!!
                 Background = "Transparent"
                 BorderThickness="0"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                 ScrollViewer.VerticalScrollBarVisibility="Disabled"               
                 Margin="0,252,0,10"
                 HorizontalAlignment="Left">
                 <ItemsControl.ItemsPanel>
                     <ItemsPanelTemplate>
                         <WrapPanel HorizontalAlignment="Left" Margin="50,0,0,0" Background="Transparent" Orientation="Vertical"/>
                     </ItemsPanelTemplate>
                 </ItemsControl.ItemsPanel>
                 <ItemsControl.ItemTemplate>
                 <DataTemplate>                  
                     <Button
                        Command="{Binding ElementName=myCustomControl, Path=DataContext.ItemClicked}">
    ....
    

1 additional answer

Sort by: Most helpful
  1. Lloyd Sheen 1,476 Reputation points
    2021-09-07T17:05:43.55+00:00

    The problem is that when you are clicking outside the ItemsControl the DataContext is the MyItemsControlViewModel. The binding works. When it is in an Item (MyElement) the DataContext of each item in the ItemsControl the binding fails so the command will not execute.