question

CarolinaGritti-4365 avatar image
0 Votes"
CarolinaGritti-4365 asked CarolinaGritti-4365 commented

WPF ItemsControl can't bind Command

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-wpfdotnet-wpf-xaml
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,@ CarolinaGritti-4365 . How is your DataContext defined? What is the definition of RelayC(OnItemSelected) in _itemClicked = new RelayC(OnItemSelected); Can you show its related code? Please show me the code of your BurgetMenuItem class.

0 Votes 0 ·

Hi!

I made some confusion while i was writing the question! I was replacing names like RelayC and BurgerMenuItem with something more generic (like MyCommand and MyElement) but i've missed some!
Please consider
RelayC > MyCommand
BurgerMenuItem > MyElement
BurgerItems> MyElementItems

Also i deleted by mistake the row

IItemsSource="{Binding MyElementItems}"

in the ItemsControls, but it is present in my code.

The component MyCustomControl is used in a page called PageUser.xaml.
In the PageUser.xaml.cs i have

      public PageUser()
      {
          InitializeComponent();
          DataContext = GuiHandler.Instance;
          myCustomComponent.DataContext = GuiHandler.Instance.MyElementModel;
      }

Where MyElementModel is an instance of MyItemsControlViewModel where MyElementItems list is populated with 3 items.
And it works, because i can see them correctly.

0 Votes 0 ·
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered CarolinaGritti-4365 commented

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
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I want to kick myself!!
I don't know how I didn't see it! Thank you very much

0 Votes 0 ·
LloydSheen-3317 avatar image
0 Votes"
LloydSheen-3317 answered CarolinaGritti-4365 commented

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.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for your reply!

I know that. But i don't know how to fix this!
IAs i found in other answers to similar question i try to change the DataContext for the Button component in an Item by doing

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

or this

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

But it doesn't work.

0 Votes 0 ·