Search code examples
c#wpfmvvmmvvm-lighticommand

WPF binding command to Datacontext inside Datagrid


I am just getting started with WPF and MVVM and managed to bind my Datagrid to the list ProductList of my DataContext ViewModel Class. However, I am now trying to bind the buttons inside my DataGrid to some Commands of my DataContext Class.

<DataGrid x:Name="myDataGrid" ItemsSource="{Binding ProductsList}" x:FieldModifier="public" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="No MAT" Binding="{Binding MATProductNumber}" Width="0.1*"/>
            <DataGridTextColumn Header="Format" Binding="{Binding tblFormat.FormatName}" Width="0.1*"/>
            <DataGridTextColumn Header="Nom produit" Binding="{Binding tblProduct.ProductName}" Width="0.1*"/>
            <DataGridTextColumn x:Name="productGradeHeader" Header="Grade" Binding="{Binding tblGrade.GradeName}" Width="0.1*"/>
            <DataGridTemplateColumn Width=".1*"           
                <DataGridTemplateColumn.HeaderTemplate> 
                     <DataTemplate>
                       <StackPanel Orientation="Horizontal">
                          <Button x:Name="leftArrowSearchButton" Command="{Binding PreviousPageCommand}" CommandParameter="1">
                            <materialDesign:PackIcon Kind="ArrowLeftThick" Width="25" Height="25" VerticalAlignment="Center"/>
                          </Button>
                          <Button x:Name="rightArrowSearchButton" Command="{Binding NextPageCommand}" CommandParameter="1">
                            <materialDesign:PackIcon Kind="ArrowRightThick" Width="25" Height="25" VerticalAlignment="Center"/>
                          </Button>
                       </StackPanel>
                     </DataTemplate>
               </DataGridTemplateColumn.HeaderTemplate>
           </DataGridTemplateColumn>
   </DataGrid.Columns>
</DataGrid>

This line right here is supposed to Bind to PreviousPageCommand in my Data context

<Button x:Name="leftArrowSearchButton" Command="{Binding PreviousPageCommand}" CommandParameter="1"  ToolTip="Voir la page précédente" Height="24" Width="53" Margin="0,0,20,0">

I have debugged and found out that it's not even calling the function. Therefore, I am almost certain that there is a problem with the binding.

It seems like my button is trying to Bind to an element of ProductsList. Is there a way of going back one level up? I have already tried binding my buttons to DataContext.PreviousPageCommand

Thanks in Advance!

Edit 1: Here is the code in the Backend as requested

 public ObservableCollection<tblMATProduct> ProductsList { get; set; }

 private void NextPageScrollCommand(string number)
 {
     Page++;
     navigate(Page, Size);
 }

 public void navigate(int page, int size)
 {
     var result = new ObservableCollection<tblMATProduct>(db.tblMATProduct.Include(s => s.tblGrade).Include(s => s.tblProduct).Include(s => s.tblFormat).OrderBy(s => s.MATProductID).Skip(page * size).Take(size).ToList());
     ProductsList = result;
 }

ProductsList is updating, I can see it in the debugger. It's only the UI that's not updating.

Edit 2: It's working fine now! Just added this line to my ProductsList setter:

set
        {
            SetProperty(ref _products, value);
        }

Solution

  • As stated in my comment you need to bind to (ViewModel) Parent/Ancestor.DataContext

    Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.PreviousPageCommand}"
    

    You'll also need to bind the SelectedItem of your DataGrid so the ViewModel knows which row the button was in when the user clicks. Or bind the DataContext of the button to the CommandParameter. like @Andy mentioned in the comment