Search code examples
c#wpfkey-bindings

TextBox KeyBinding not found


Used for understanding: https://learn.microsoft.com/de-de/dotnet/api/system.windows.input.inputbinding?view=netframework-4.6.1

public MainWindow() {
  insertNewScoreCommand = new SimpleDelegateCommand(x => this.InsertNewScore(x));

  insertNewScoreCommand.GestureKey = Key.Enter;
  insertNewScoreCommand.GestureModifier = ModifierKeys.Control;
  insertNewScoreCommand.MouseGesture = MouseAction.RightClick;
}

public SimpleDelegateCommand InsertNewScoreCommand {
   get { return insertNewScoreCommand; }
}

private SimpleDelegateCommand insertNewScoreCommand;
private void InsertNewScore(object sender)    {        }

I have an input field inside of a DataGrip which I want to use for inserting new scores to the database. My thought was to trigger a method when I hit Enter in the field.

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=Disciplines}" HeadersVisibility="None" CanUserAddRows="False"  CanUserDeleteRows="False" Margin="0" BorderThickness="0">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Path=DisciplineId}" IsReadOnly="True" Visibility="Hidden" />
    <DataGridTextColumn Binding="{Binding Path=Name }" IsReadOnly="True" Width="70"/>
    <DataGridTemplateColumn Width="*" MinWidth="52">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBox MinWidth="50" >
            <TextBox.InputBindings>
              <KeyBinding Key="Return" Command="{Binding InsertNewScoreCommand}" />
            </TextBox.InputBindings>
          </TextBox>
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

But WPF keeps saying that the binding does not exist. It's the first time I do an KeyBinding and I don't understand what is wrong. I thought I have done all which is in the docu.

System.Windows.Data Error: 40 : BindingExpression path error: 'InsertNewScoreCommand' property not found on 'object' ''Discipline_A320C92756365475DEC4BDC8039368751EFACDCE5B74C1FE572674EA0C24C666' (HashCode=39958021)'. BindingExpression:Path=InsertNewScoreCommand; DataItem='Discipline_A320C92756365475DEC4BDC8039368751EFACDCE5B74C1FE572674EA0C24C666' (HashCode=39958021); target element is 'KeyBinding' (HashCode=18759866); target property is 'Command' (type 'ICommand')

Edit: Link to the complete source code


Solution

  • Binding will look for a specified binding Path in current binding context. By default it will be current DataContext. You can change binding context by using either ElementName, Source or RelativeSource. In your case assuming your InsertNewScoreCommand and DataGrid DataContext are in same ViewModel, you can use your DataGrid DataContext.

    <DataGrid x:Name="disciplinesDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Path=Disciplines}" HeadersVisibility="None" CanUserAddRows="False"  CanUserDeleteRows="False" Margin="0" BorderThickness="0">
       <DataGrid.Columns>
           <DataGridTextColumn Binding="{Binding Path=DisciplineId}" IsReadOnly="True" Visibility="Hidden" />
           <DataGridTextColumn Binding="{Binding Path=Name }" IsReadOnly="True" Width="70"/>
           <DataGridTemplateColumn Width="*" MinWidth="52">
           <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                   <TextBox MinWidth="50" >
                       <TextBox.InputBindings>
                           <KeyBinding Key="Return" Command="{Binding ElementName=disciplinesDataGrid, Path=InsertNewScoreCommand}" />
                       </TextBox.InputBindings>
                   </TextBox>
               </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
      </DataGrid.Columns>
    </DataGrid>