Good day. I try to make so that the DoubleClick team would work only on DataGridRow. I use the dependency property:
public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached( "DoubleClickCommand", typeof(ICommand), typeof(DataGridRowBehavior), new UIPropertyMetadata(DoubleClick_PropertyChanged)); public static void SetDoubleClickCommand(DependencyObject target, ICommand value) { target.SetValue(DataGridRowBehavior.DoubleClickCommandProperty, value); } public static ICommand GetDoubleClickCommand(UIElement element) { return (ICommand)element.GetValue(DoubleClickCommandProperty); } private static void DoubleClick_PropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { var element = target as System.Windows.Controls.DataGrid; if (element == null) { throw new System.InvalidOperationException("This behavior can be attached to a DataGridRow item only."); } if ((e.NewValue != null) && (e.OldValue == null)) { element.PreviewMouseDoubleClick += OnPreviewMouseDoubleClick; } else if ((e.NewValue == null) && (e.OldValue != null)) { element.PreviewMouseDoubleClick -= OnPreviewMouseDoubleClick; } } private static void OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) { DependencyObject obj = sender as DependencyObject; ICommand cmd = (ICommand)obj.GetValue(DoubleClickCommandProperty); if (cmd != null) { if (cmd.CanExecute(obj)) cmd.Execute(obj); } } In the view I have the following:
. . . <Window.Resources> <Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}"> <Setter Property="help:DataGridRowBehavior.DoubleClickCommand" Value="{Binding local:EditProduct}" /> </Style> </Window.Resources> . . . <DataGrid Grid.Row="1" x:Name="MyDG" ItemsSource="{Binding Path=ProductCol}" RowStyle="{StaticResource DefaultRowStyle}" SelectedItem="{Binding Path=CurrentProduct}" AutoGenerateColumns="True" CanUserAddRows="False" SelectionUnit="FullRow" IsReadOnly="True"> </DataGrid> And in the ViewModel it looks like this:
class MainWindowViewModel : ViewModelBase { private Product currentProduct; public Product CurrentProduct { get { return currentProduct; } set { currentProduct = value; Debug.WriteLine(currentProduct.Id); OnPropertyChanged("CurrentProduct"); } } ObservableCollection<Product> product; public ObservableCollection<Product> ProductCol { get { if (product == null) product = new ObservableCollection<Product>(); return product; } } public MainWindowViewModel() { ProductCol.Add( new Product() {Id = 1, Code = 5236}); ProductCol.Add(new Product() { Id = 2, Code = 2857 }); ProductCol.Add(new Product() { Id = 3, Code = 7851 }); } RelayCommand editProduct; public ICommand EditProduct { get { if (editProduct == null) editProduct = new RelayCommand(ExecuteEditCurrentProductCommand, CanExecuteEditCurrentProductCommand); return editProduct; } } private bool CanExecuteEditCurrentProductCommand(object obj) { return CurrentProduct == null ? false : true; } private void ExecuteEditCurrentProductCommand(object obj) { var oEW = new ObjectEditorWindow(); var vm = new ObjectEditorViewModel<Product>(); vm.SelectedObject = CurrentProduct; oEW.DataContext = vm; oEW.ShowDialog(); } protected override void OnDispose() { this.ProductCol.Clear(); } } Drew attention to just such a mistake ...
System.Windows.Data Error: 40 : BindingExpression path error: 'EditProduct' property not found on 'object' ''Product' (HashCode=53239939)'. BindingExpression:Path=EditProduct; DataItem='Product' (HashCode=53239939); target element is 'DataGridRow' (Name=''); target property is 'DoubleClickCommand' (type 'ICommand') As I understand the compiler is looking for the property EditProduct in the class Product. If so, why is this? Help, please, sort it out.