1
votes

I'm working on a small WPF application and I would like to present a list of strings to the user which they may edit, add to, or delete from.

The first thing I've done is create a base class with view model change notification:

  public abstract class BaseViewModel : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

After this, I created a wrapper for strings for binding/change notification:

  public class StringViewModel : BaseViewModel
  {
    private string value;

    public string Value
    {
      get { return this.value; }
      set
      {
        if (value == this.value) return;
        this.value = value;
        this.RaisePropertyChanged(nameof(this.Value));
      }
    }
  }

Then I have a view model which uses this class (I have elided other members which are not relevant):

  public class UserSettingsDataViewModel : BaseViewModel
  {
    private ObservableCollection<StringViewModel> blacklistedFiles;

    public ObservableCollection<StringViewModel> BlacklistedFiles
    {
      get { return this.blacklistedFiles; }
      set
      {
        if (Equals(value, this.blacklistedFiles)) return;
        this.blacklistedFiles = value;
        this.RaisePropertyChanged(nameof(this.BlacklistedFiles));
      }
    }
  }

Finally, I have included this in my XAML for the screen in question:

<WrapPanel>
  <Label>Blacklisted files</Label>
  <DataGrid ItemsSource="{Binding Data.BlacklistedFiles}" AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTextColumn Binding="{Binding Value}" Header="File name" />
      <DataGridTemplateColumn Header="Remove">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <Button Content="Remove" Command="Delete" />
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
    </DataGrid.Columns>
  </DataGrid>
</WrapPanel>

Everything works, except I cannot edit the values of new or existing members. I can click on the cell and get it to enter editing mode, but pressing keys does nothing (except I do seem to be able to add or remove spaces). I feel like there must be a straightforward fix for this but it is eluding me.

1

1 Answers

1
votes

This turns out to be because this WPF form exists inside a Windows Forms application. The steps to resolve were:

  • Add a reference to the WindowsFormsIntegration library.

  • In the class that creates the window, add the using statement using Systems.Windows.Forms.Integration.

  • Call ElementHost.EnableModelessKeyboardInterop on the window.

I have to give some credit to this answer, which helped me figure out what was wrong.