1장. WPF Binding 이용하여 프로젝트 실습
- C#/WPF
- 2022. 6. 16. 21:47
목적
- WPF Binding 기술을 이용하여 주소록 관리 프로그램을 실습합니다.
요구사항
- DataGrid 컨트롤 하나를 추가하여 주소록 관리 목록을 보여줍니다.
- Button 컨트롤은 4개로, 추가, 삭제, 변경, 종료 4개의 버튼을 추가합니다.
- 추가 버튼을 클릭하면, 회원을 추가하는 Sub 창이 출력됩니다.
- 삭제 버튼을 클릭하면, 목록에서 선택된 데이터가 삭제됩니다.
- 변경 버튼을 클릭하면, Sub 화면에 해당 열의 내용이 출력됩니다.
- 종료 버튼을 누르면 프로그램이 종료됩니다.
실습
요구사항 대로 프로젝트를 생성하여 실습합니다.
MainView.xaml
<Window x:Class="BindingTest.MainView"
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:BindingTest"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:MainView}"
Title="MainView" Height="328" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid HorizontalAlignment="Left"
Margin="10, 10, 0, 0" VerticalAlignment="Top"
Width="497"
SelectedIndex="{Binding Path=SelectedIndex,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"
ItemsSource="{Binding Path=Persons,
UpdateSourceTrigger=PropertyChanged,
Mode=OneWay}"
AutoGenerateColumns="False"
IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="이름" Width="100"
Binding="{Binding Path=Name}"/>
<DataGridTextColumn Header="성별"
Binding="{Binding Path=Gender}"/>
<DataGridTextColumn Header="전화번호" Width="150"
Binding="{Binding Path=PhoneNumber}"/>
<DataGridTextColumn Header="주소" Width="*"
Binding="{Binding Path=Address}"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="추가"
HorizontalAlignment="Left" Margin="192,249,0,0"
VerticalAlignment="Top" Width="75"
Command="{Binding AddCommand}"/>
<Button Content="삭제"
HorizontalAlignment="Left" Margin="272, 249,0,0"
VerticalAlignment="Top" Width="75"
Command="{Binding DeleteCommand}"/>
<Button Content="변경"
HorizontalAlignment="Left" Margin="352,249,0,0"
VerticalAlignment="Top" Width="75"
Command="{Binding ModifyCommand}"/>
<Button Content="종료"
HorizontalAlignment="Left" Margin="432,249,0,0"
VerticalAlignment="Top" Width="75"
Command="{Binding ExitCommand}"/>
</Grid>
</Window>
- MainView.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace BindingTest
{
/// <summary>
/// MainView.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainView : Window, INotifyPropertyChanged
{
/// <summary>
/// SelectedIndex Property
/// </summary>
private int _selectedIndex;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
OnPropertyChanged();
}
}
public DelegateCommand AddCommand { get; set; }
public DelegateCommand DeleteCommand { get; set; }
public DelegateCommand ModifyCommand { get; set; }
public DelegateCommand ExitCommand { get; set; }
public ObservableCollection<Person> Persons { get; set; }
public MainView()
{
InitializeComponent();
this.DataContext = this;
Persons = new ObservableCollection<Person>(); //ObservableCollection 객체 생성
#region
Persons.Add(new Person() { Address = "test1", Name = "홍길동1", Gender = true, PhoneNumber = "11111" });
Persons.Add(new Person() { Address = "test2", Name = "홍길동2", Gender = true, PhoneNumber = "22222" });
Persons.Add(new Person() { Address = "test3", Name = "홍길동3", Gender = true, PhoneNumber = "33333" });
Persons.Add(new Person() { Address = "test4", Name = "홍길동4", Gender = false, PhoneNumber = "44444" });
#endregion
AddCommand = new DelegateCommand(_addCommandAction);
DeleteCommand = new DelegateCommand(_deleteCommandAction);
ModifyCommand = new DelegateCommand(_modifyCommandAction);
ExitCommand = new DelegateCommand(_exitCommandAction);
}
private void _addCommandAction(object obj)
{
AddView add = new AddView();
if(add.ShowDialog() == true)
{
Persons.Add(add.PersonData);
}
}
private void _exitCommandAction(object obj)
{
this.Close();
}
private void _deleteCommandAction(object obj)
{
if(SelectedIndex < 0)
{
MessageBox.Show("선택된 데이터가 없습니다.", "주소록 v0.1",
MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
Persons.RemoveAt(SelectedIndex); //선택된 Person 삭제
}
private void _modifyCommandAction(object obj)
{
if(SelectedIndex < 0)
{
MessageBox.Show("선택된 데이터가 없습니다.", "주소록 v0.1",
MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
var selectData = Persons[SelectedIndex];
var modifyData = new Person(selectData);
AddView modify = new AddView(modifyData, AddView.ViewType.Modify);
modify.PersonData = new Person(modifyData);
if(modify.ShowDialog() == true)
{
Persons[SelectedIndex] = modify.PersonData;
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
- AddView.xaml
<Window x:Class="BindingTest.AddView"
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:BindingTest"
mc:Ignorable="d"
Title="{Binding Path=Caption, UpdateSourceTrigger=PropertyChanged}" Height="300" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0"
Content="이름"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1"
Width="200" Margin="4"
Text="{Binding Path=PersonData.Name,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"/>
<Label Grid.Row="1" Grid.Column="0"
Content="성별"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1"
Width="200" Margin="4"
Text="{Binding Path=PersonData.Gender,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"/>
<Label Grid.Row="2" Grid.Column="0"
Content="전화번호"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBox Grid.Row="2" Grid.Column="1"
Width="200" Margin="4"
Text="{Binding Path=PersonData.PhoneNumber,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"/>
<Label Grid.Row="3" Grid.Column="0"
Content="주소"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBox Grid.Row="3" Grid.Column="1"
Width="200" Height="150" Margin="4"
Text="{Binding Path=PersonData.Address,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}"/>
<Grid Grid.Row="4" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Margin="5"
Content="확인"
Command="{Binding OkCommand}"/>
<Button Grid.Column="1" Margin="5"
Content="취소"
Command="{Binding CancelCommand}"/>
</Grid>
</Grid>
</Window>
- AddView.xaml.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace BindingTest
{
/// <summary>
/// AddView.xaml에 대한 상호 작용 논리
/// </summary>
public partial class AddView : Window, INotifyPropertyChanged
{
public enum ViewType
{
Add, Modify
}
private string _caption = "Title";
public string Caption
{
get { return _caption; }
set
{
_caption = value;
OnPropertyChanged();
}
}
public AddView(Person modifyData = null, ViewType type = ViewType.Add)
{
InitializeComponent();
this.DataContext = this;
if(type == ViewType.Add)
{
Caption = "추가";
PersonData = new Person();
}
else if(type == ViewType.Modify)
{
Caption = "변경";
PersonData = modifyData;
}
else
{
Caption = "추가";
PersonData = new Person();
}
OkCommand = new DelegateCommand(_okCommandAction);
CancelCommand = new DelegateCommand(_cancelCommandAction);
}
public Person PersonData { get; set; }
public DelegateCommand OkCommand { get; set; }
public DelegateCommand CancelCommand { get; set; }
private void _cancelCommandAction(object obj)
{
DialogResult = false;
this.Close();
}
private void _okCommandAction(object obj)
{
DialogResult = true;
this.Close();
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
- DelegateCommand.cs
using System;
using System.Windows.Input;
namespace BindingTest
{
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute) : this(execute, null) { }
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if(_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
- Person.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace BindingTest
{
public class Person : INotifyPropertyChanged
{
#region INotifyPropertyChaged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public Person() { }
public Person(Person input) { }
/// <summary>
/// Name Property
/// </summary>
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
//CallerMemberName 이 자동으로 해당 Property 이름 찾아서 반환
//값이 반환되면 Event 실행 = UI에 변화된 값 변경
OnPropertyChanged();
}
}
/// <summary>
/// Gender Property
/// </summary>
private bool _gender = false;
public bool Gender
{
get { return _gender; }
set
{
_gender = value;
OnPropertyChanged();
}
}
/// <summary>
/// PhoneNumber Property
/// </summary>
private string _phoneNumber = string.Empty;
public string PhoneNumber
{
get { return _phoneNumber; }
set
{
_phoneNumber = value;
OnPropertyChanged();
}
}
/// <summary>
/// Address Property
/// </summary>
private string _address = string.Empty;
public string Address
{
get { return _address; }
set
{
_address = value;
OnPropertyChanged();
}
}
}
}
- 실행결과
728x90
'C# > WPF' 카테고리의 다른 글
[WPF] WPF DevExpress.ReactiveUI 실습 (0) | 2022.06.17 |
---|---|
2장. WPF MVVM 실습 (2) | 2022.06.16 |
[WPF] WPF 점선 그리기 (0) | 2022.01.06 |
[WPF 기본 문법] WPF TextBlock, Button 컨트롤 Style 사용하기 (0) | 2021.12.28 |
[WPF] WPF ProgressBar 컨트롤 MVVM 패턴으로 구현하기 (3) | 2021.11.27 |
이 글을 공유하기