MVVM패턴에서 View에서 발생한 DataGrid의 더블클릭 이벤트를 DataGrid.InputBindings으로 받을 수 있습니다. 하지만 더블클릭 이벤트의 발생만 알 수 있고 선택한 DataGridRow를 ViewModel로 전달할 수는 없습니다. 더블클릭 시 선택한 DataGridRow를 ViewModel에 전달하는 예제코드입니다.
✅ Behavior를 사용한 DataGrid 더블 클릭 이벤트
NuGet 패키지 관리자를 사용하여 Microsoft.Xaml.Behaviors.Wpf 패키지를 프로젝트에 추가해야 합니다.
UIHelper.cs
namespace MVVM
{
public static class UIHelpers
{
public static T TryFindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = GetParentObject(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
return TryFindParent<T>(parentObject);
}
}
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
DependencyObject parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
FrameworkContentElement fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
return VisualTreeHelper.GetParent(child);
}
public static void UpdateBindingSources(DependencyObject obj, params DependencyProperty[] properties)
{
foreach (DependencyProperty depProperty in properties)
{
BindingExpression be = BindingOperations.GetBindingExpression(obj, depProperty);
if (be != null) be.UpdateSource();
}
int count = VisualTreeHelper.GetChildrenCount(obj);
for (int i = 0; i < count; i++)
{
DependencyObject childObject = VisualTreeHelper.GetChild(obj, i);
UpdateBindingSources(childObject, properties);
}
}
public static T TryFindFromPoint<T>(UIElement reference, Point point) where T : DependencyObject
{
DependencyObject element = reference.InputHitTest(point) as DependencyObject;
if (element == null) return null;
else if (element is T) return (T)element;
else return TryFindParent<T>(element);
}
}
}
View에서 특정 UI 요소를 검색하는 Class입니다.
원본 소스코드는 파일로 첨부합니다.
DataGridDoubleClickBehavior.cs
public class DataGridDoubleClickBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseDoubleClick += AssociatedObject_MouseDoubleClick;
}
private void AssociatedObject_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DataGrid dataGrid = (DataGrid)sender;
var dgRow = UIHelpers.TryFindFromPoint<DataGridRow>(dataGrid, point: e.GetPosition(dataGrid));
dataGrid.SelectedIndex = dgRow.GetIndex();
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseDoubleClick -= AssociatedObject_MouseDoubleClick;
}
}
Behavior에 MouseDoubleClick을 등록하여 동작을 정의합니다.
UIHelpers 클래스를 통해 클릭한 마우스 위치의 control을 찾습니다.
Model
public class SomeData
{
public int Number { get; set; }
public string Name { get; set; }
}
ViewModel
private ObservableCollection<SomeData> _someDataCollection = new ObservableCollection<SomeData>();
public ObservableCollection<SomeData> SomeDataDataCollection
{
get => _someDataCollection;
set { _someDataCollection = value; OnPropertyChanged(nameof(SomeDataDataCollection)); }
}
private SomeData _selectedItemVm;
public SomeData SelectedItemVm
{
get => _selectedItemVm;
set {
_selectedItemVm = value;
OnPropertyChanged(nameof(SelectedItemVm));
OnSelectedDataGridItemChanged(_selectedItemVm);
}
}
public MainViewModel()
{
// 테스트 데이터 생성
for (int i = 0; i < 50; i++)
{
SomeDataDataCollection.Add(new SomeData() { Name = $"name({i})", Number = i + 1 });
}
}
private RelayCommand<object> _selectedDataGridItemChangedCommand;
public RelayCommand<object> SelectedDataGridItemChangedCommand
{
get
{
if (_selectedDataGridItemChangedCommand == null)
_selectedDataGridItemChangedCommand = new RelayCommand<object>(OnSelectedDataGridItemChanged);
return _selectedDataGridItemChangedCommand;
}
}
private void OnSelectedDataGridItemChanged(object obj)
{
// Do something.
}
OnSelectedDataGridItemChanged 가 호출될 때 _selectedItemVm와 obj에 선택된 DataGridRow가 들어있습니다.
xaml 사용법
<xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors">
<DataGrid ItemsSource="{Binding SomeDataCollection}">
<behavior:Interaction.Behaviors>
<local:DataGridDoubleClickBehavior/>
</behavior:Interaction.Behaviors>
</DataGrid>
✅ Behavior를 사용한 DataGrid 더블 클릭 이벤트 - 끝
관련 포스팅
DataGrid: 배경색으로 Row를 구분하는 간단한 방법 #1
DataGrid: 배경색으로 Row를 구분하는 간단한 방법 #2