I have a WPF Datagrid that I am capturing the paste command via
<CommandBinding Command="{x:Static ApplicationCommands.Paste}"
Executed="CommandBinding_Paste_Executed"/>
In 'CommandBinding_Paste_Executed' I can cycle through all the selected cells and can see the field name, where I need to paste the clipboard data to my observable collection.
Unfortunately I cannot figure out how to reference the member of the collection. I realise the below is wrong, but it should give you an idea as to what I am attempting...
foreach (DataGridCellInfo cell in MyDataGrid.SelectedCells)
{
string columnName = cell.Column.SortMemberPath;
int rowIndex = ????;
MyCollection[rowIndex].columnName ??? = Clipboard.GetText();
}
Am I missing something obvious? Or am I attempting this from the wrong angle.
OK, so it appear after searching Google for wpf datagrid paste, what I should have been looking for is column mapping. Still find it hard to believe that these is not a simpler answer for this, but here is what I have got. MainWindow.xaml
<Grid>
<DataGrid x:Name="DGrid" ItemsSource="{Binding Path=Stuff}"
SelectedItem="{Binding DGSelection}"
CellEditEnding="DGrid_CellEditEnding"
SelectionUnit="Cell">
<DataGrid.CommandBindings>
<CommandBinding Command="{x:Static ApplicationCommands.Paste}" CanExecute="CanPaste" Executed="Paste"/>
</DataGrid.CommandBindings>
<DataGrid.Columns>
<DataGridTextColumn Header="First name" Binding="{Binding FirstName}"/>
<DataGridTextColumn Header="Surname" Binding="{Binding Surname}"/>
<DataGridTextColumn Header="Country" Binding="{Binding Country}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
Person.cs
public class Person : INotifyPropertyChanged
{
public string FirstName { get; set; }
public string Surname { get; set; }
public string Country { get; set; }
public Person()
{ }
public Person(string firstName, string surname, string country)
{
FirstName = firstName;
Surname = surname;
Country = country;
}
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
PeopleViewModel.cs
public class PeopleViewModel : INotifyPropertyChanged
{
private ObservableCollection<Person> people;
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// property map to store the column indexes and names
/// eg: 0, FirstName
/// </summary>
private Dictionary<int, string> propertyMap;
public PeopleViewModel()
{
people = new ObservableCollection<Person>();
people.Add(new Person("Bruce", "Willis", "USA"));
people.Add(new Person("Sarah", "Connor", "USA"));
people.Add(new Person("Adolph", "Hitler", "Germany"));
people.Add(new Person("Rowan", "Atkinson", "United Kingdom"));
people.Add(new Person("Ryan", "Reynolds", "Canada"));
propertyMap = new Dictionary<int, string>();
}
public ObservableCollection<Person> PeopleList
{
get => people;
set
{
people = value;
OnPropertyChanged("PeopleList");
}
}
public void AddColumnMapping(int displayIndex, string propertyName)
{
propertyMap[displayIndex] = propertyName;
}
private void SetProperty(Person person, string propertyName, string cellItem)
{
PropertyInfo propertyInfo = person.GetType().GetProperty(propertyName);
if (propertyInfo == null)
throw new Exception($"Could not find property '{propertyName}'");
if (propertyInfo.PropertyType != typeof(string))
throw new Exception("Only coded for string values at this time");
propertyInfo.SetValue(person, cellItem, null);
person.OnPropertyChanged(propertyName);
}
public void Paste(int row, string column, string value)
{
Person person = PeopleList[row];
SetProperty(person, column, value);
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public PeopleViewModel people = new PeopleViewModel();
public MainWindow()
{
InitializeComponent();
DGrid.ItemsSource = people.PeopleList;
}
private void CanPaste(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = Clipboard.GetDataObject() != null;
}
private void Paste(object sender, ExecutedRoutedEventArgs e)
{
Person person;
int row;
string column;
string clipboardValue = Clipboard.GetText();
if (clipboardValue.Substring(clipboardValue.Length - 2) == "\r\n")
clipboardValue = clipboardValue.Substring(0, clipboardValue.Length - 2);
IList<DataGridCellInfo> cells = DGrid.SelectedCells;
foreach (DataGridCellInfo cell in cells)
{
person = cell.Item as Person;
row = people.PeopleList.IndexOf(person);
column = cell.Column.SortMemberPath;
people.Paste(row, column, clipboardValue);
}
}
}
My thanks for Peter_Smithson at https://www.codeproject.com/Articles/246306/Implementing-Copy-Paste-for-WPF-DataGrid-net-4
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.