MVVM을 사용하여 WPF Datagrid에서 행 제거
페이지 정보
작성자 GrapeCity 작성일 2022-05-19 10:43 조회 2,880회 댓글 0건본문
관련링크
MVVM(Model-View-ViewModel) 디자인 패턴의 인기를 고려하여 WPF 개발자는 XAML에서 가능한 모든 기능을 구현하는 방법을 항상 찾고 있습니다.
이로 인해 View의 "코드 숨김"에서 연결 해제된 코드(View 클래스를 초기화하는 VB.NET 코드 또는 C#) 없이 View(XAML) 및 ViewModel 간에 모든 항목을 원활하게 바인딩할 수 있습니다.
이 코드 예시에서는 WPF datagrid 컨트롤 내에 포함된 Button이 ViewModel에 바인딩되도록 구성하는 방법을 보여드리겠습니다. Button은 행 제거와 같이 데이터 작업을 수행할 수 있도록 행의 데이터 객체를 전달합니다.
이 블로그에서 참조한 샘플은 에서 이전에 만들었지만 이 시나리오에서 약간 수정해 보겠습니다.
FlexGrid에 Button 추가
셀 템플릿을 사용자 정의하여 FlexGrid 셀에서 Button(또는 모든 UI 요소)을 표시할 수 있습니다. 이를 수행하는 가장 쉬운 방법은 모든 열을 정의하고 AutoGenerateColumns를 false로 설정하는 XAML에 있습니다.
<c1:C1FlexGrid ItemsSource="{Binding EmployeeList}" AutoGenerateColumns="False"> <c1:C1FlexGrid.Columns> <c1:Column Binding="{Binding FirstName}"/> <c1:Column Binding="{Binding LastName}"/> <c1:Column Binding="{Binding Age}"/> <c1:Column Header="Remove"> <c1:Column.CellTemplate> <DataTemplate> <Grid> <Button Content="Delete Record" Command="TO DO"/> </Grid> </DataTemplate> </c1:Column.CellTemplate> </c1:Column> </c1:C1FlexGrid.Columns> </c1:C1FlexGrid>
Button은 아직 완전히 연결되지 않았습니다. ViewModel 및 Command를 설정하면 다시 설명하겠습니다. FlexGrid 시작 방법에 대한 자세한 내용은 를 확인하시기 바랍니다.
ViewModel 만들기
ViewModel은 View에 대한 데이터 소스 역할을 하므로 View에 동적으로 표시하고자 하는 데이터와 관련된 항목은 ViewModel을 통해 컨트롤해야 합니다. 가장 기본적인 이 샘플에서 ViewModel에는 두 가지가 필요합니다. 데이터 컬렉션과 데이터 행을 제거할 명령입니다.
데이터 컬렉션의 경우에는 직원 목록을 노출합니다. 일반적으로 View 및 ViewModel은 View에 속성 업데이트를 전달할 수 있도록 를 구현합니다.
또다른 대안으로 목록을 작업하는 경우 ObservableCollection을 사용합니다. 여기에는 ObservableCollection에 바인딩된 모든 UI의 기본 제공 업데이트 알림이 포함됩니다.
class EmployeeListView { ICommand m_RowRemoveCommand; ObservableCollection<Employee> _list; public EmployeeListView() { } public ObservableCollection<Employee> EmployeeList { get { if (_list == null) { _list = new ObservableCollection<Employee>(); _list.Add(new Employee() { FirstName = "John", LastName = "Wayne", Age = 35 }); _list.Add(new Employee() { FirstName = "Maximus", LastName = "Decimus", Age = 33 }); _list.Add(new Employee() { FirstName = "Alexander", LastName = "Conklin", Age = 42 }); _list.Add(new Employee() { FirstName = "Jason", LastName = "Bourne", Age = 66 }); } return _list; } } public ICommand RemoveCommand { get { if (m_RowRemoveCommand == null) { m_RowRemoveCommand = new DelegateCommand(CanRemoveRow, RemoveRow); } return m_RowRemoveCommand; } } private void RemoveRow(object parameter) { int index = EmployeeList.IndexOf(parameter as Employee); if (index > -1 && index < EmployeeList.Count) { EmployeeList.RemoveAt(index); } } private bool CanRemoveRow(object parameter) { return true; } }
명령의 경우에는 RemoveCommand라는 ICommand를 노출합니다. 이 명령은 Execute 메서드와 CanExecute 메서드에 대한 두 개의 위임 매개 변수를 취합니다. 비즈니스 로직을 구현하는 이러한 두 개의 메서드 내에 있으며 ViewModel에는 100% 여기에 있고 View에는 없습니다.
DelegateCommand는 아래 표시된 대로 일반적인 구현입니다. 이를 프로젝트에 복사하여 MVVM 명령에 사용하면 됩니다.
class DelegateCommand : ICommand { Predicate<object> canExecute; Action<object> execute; public DelegateCommand(Predicate<object> _canexecute, Action<object> _execute): this() { canExecute = _canexecute; execute = _execute; } public DelegateCommand() { } public bool CanExecute(object parameter) { return canExecute == null ? true : canExecute(parameter); } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { execute(parameter); } }
명령 바인딩
이제 ViewModel에는 RemoveCommand가 정의되었으며 RemoveRow 실행 메서드가 구현되었고(행을 제거할 실제 로직) 직원 목록은 ObservableCollection이고(따라서 업데이트는 View에 자동으로 표시됨) 명령 바인딩을 완성할 수 있습니다.
View의 Button은 Command 속성을 설정하여 ViewModel에 바인딩할 수 있습니다. 이 경우에는 RemoveCommand입니다.
<c1:Column Header="Remove"> <c1:Column.CellTemplate> <DataTemplate> <Grid> <Button Content="Delete Record" Command="{Binding Path=DataContext.RemoveCommand,RelativeSource={RelativeSource AncestorType={x:Type c1:C1FlexGrid}}}" CommandParameter="{Binding}"/> </Grid> </DataTemplate> </c1:Column.CellTemplate> </c1:Column>
여기에서는 또한 FlexGrid의 바인딩 행을 매개 변수로 전달합니다. 바인딩이 단순히 "{Binding}"인 경우는 현재 데이터 컨텍스트를 취한다는 의미입니다. FlexGrid의 행에서 컨텍스트는 해당 행의 데이터 레코드가 됩니다. RemoveRow 구현에서 위를 살펴보면 매개 변수가 사용되는 방법을 확인할 수 있습니다.
ViewModel에 바인딩
이어가기 전에 이 모든 사항 중에서 가장 중요한 부분인 ViewModel에 View를 연결하는 방법에 대해 설명해드리겠습니다. 여기에는 많은 방법이 있지만 핵심은 View의 DataContext 속성을 ViewModel의 인스턴스로 설정하는 것입니다. 아래 표시된 대로 코드에서 또는 XAML에서 이를 수행할 수 있습니다.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:CommandBindingWpf" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" x:Class="CommandBindingWpf.MainWindow" mc:Ignorable="d" xmlns:ViewModel="clr-namespace:CommandBindingWpf.ViewModel" Title="MainWindow" Height="450" Width="800"> <Window.DataContext> <ViewModel:EmployeeListView /> </Window.DataContext>
이 샘플 코드는 이 블로그와 이전 블로그인 의 주제를 함께 다룹니다. 샘플에 표시된 추가 기능은 정확한 직원을 검색하기 위해 IndexOf 메서드를 사용할 수 있도록 IEquatable을 구현하는 방법입니다.
지금 바로 ComponentOne을 다운로드하여 직접 테스트해보세요!
댓글목록
등록된 댓글이 없습니다.