728x90
반응형
728x170
▶ PersonModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TestProject;
/// <summary>
/// 사람 모델
/// </summary>
public class PersonModel : INotifyPropertyChanged
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Event
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 속성 변경시 - PropertyChanged
/// <summary>
/// 속성 변경시
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 성명
/// </summary>
private string name;
/// <summary>
/// 나이
/// </summary>
private double age;
/// <summary>
/// 기술
/// </summary>
private string skill;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 성명 - Name
/// <summary>
/// 성명
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
SetPropertyValue(ref this.name, value);
}
}
#endregion
#region 나이 - Age
/// <summary>
/// 나이
/// </summary>
public double Age
{
get
{
return this.age;
}
set
{
SetPropertyValue(ref this.age, value);
}
}
#endregion
#region 기술 - Skill
/// <summary>
/// 기술
/// </summary>
public string Skill
{
get
{
return this.skill;
}
set
{
SetPropertyValue(ref this.skill, value);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 문자열 구하기 - ToString()
/// <summary>
/// 문자열 구하기
/// </summary>
/// <returns>문자열</returns>
public override string ToString()
{
return $"{Name}, {Age}세";
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 속성 변경시 이벤트 발생시키기 - FirePropertyChangedEvent(propertyName)
/// <summary>
/// 속성 변경시 이벤트 발생시키기
/// </summary>
/// <param name="propertyName">속성명</param>
protected void FirePropertyChangedEvent([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 속성 값 설정하기 - SetPropertyValue<TProperty>(field, value, propertyName)
/// <summary>
/// 속성 값 설정하기
/// </summary>
/// <typeparam name="TProperty">속성 타입</typeparam>
/// <param name="field">필드</param>
/// <param name="value">값</param>
/// <param name="propertyName">속성명</param>
/// <returns>처리 결과</returns>
private bool SetPropertyValue<TProperty>(ref TProperty field, TProperty value, [CallerMemberName] string propertyName = null)
{
if(object.Equals(field, value))
{
return false;
}
field = value;
FirePropertyChangedEvent(propertyName);
return true;
}
#endregion
}
728x90
▶ MainPageViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace TestProject;
/// <summary>
/// 메인 페이지 뷰 모델
/// </summary>
public class MainPageViewModel : INotifyPropertyChanged
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Event
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 속성 변경시 - PropertyChanged
/// <summary>
/// 속성 변경시
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 편집 사람
/// </summary>
private PersonModel editPerson;
/// <summary>
/// 편집 여부
/// </summary>
private bool isEditing;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 편집 사람 - EditPerson
/// <summary>
/// 편집 사람
/// </summary>
public PersonModel EditPerson
{
set
{
SetPropertyValue(ref this.editPerson, value);
}
get
{
return this.editPerson;
}
}
#endregion
#region 편집 여부 - IsEditing
/// <summary>
/// 편집 여부
/// </summary>
public bool IsEditing
{
private set
{
SetPropertyValue(ref this.isEditing, value);
}
get
{
return this.isEditing;
}
}
#endregion
#region 신규 명령 - NewCommand
/// <summary>
/// 신규 명령
/// </summary>
public ICommand NewCommand { private set; get; }
#endregion
#region 제출 명령 - SubmitCommand
/// <summary>
/// 제출 명령
/// </summary>
public ICommand SubmitCommand { private set; get; }
#endregion
#region 취소 명령 - CancelCommand
/// <summary>
/// 취소 명령
/// </summary>
public ICommand CancelCommand { private set; get; }
#endregion
#region 사람 리스트 - PersonList
/// <summary>
/// 사람 리스트
/// </summary>
public IList<PersonModel> PersonList { get; } = new ObservableCollection<PersonModel>();
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainPageViewModel()
/// <summary>
/// 생성자
/// </summary>
public MainPageViewModel()
{
NewCommand = new Command
(
execute : () =>
{
EditPerson = new PersonModel();
EditPerson.PropertyChanged += editPerson_PropertyChanged;
IsEditing = true;
ChangeCanExecute();
},
canExecute : () =>
{
return !IsEditing;
}
);
SubmitCommand = new Command
(
execute : () =>
{
PersonList.Add(EditPerson);
EditPerson.PropertyChanged -= editPerson_PropertyChanged;
EditPerson = null;
IsEditing = false;
ChangeCanExecute();
},
canExecute : () =>
{
return EditPerson != null &&
EditPerson.Name != null &&
EditPerson.Name.Length > 1 &&
EditPerson.Age > 0;
}
);
CancelCommand = new Command
(
execute : () =>
{
EditPerson.PropertyChanged -= editPerson_PropertyChanged;
EditPerson = null;
IsEditing = false;
ChangeCanExecute();
},
canExecute : () =>
{
return IsEditing;
}
);
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 속성 변경시 이벤트 발생시키기 - FirePropertyChangedEvent(propertyName)
/// <summary>
/// 속성 변경시 이벤트 발생시키기
/// </summary>
/// <param name="propertyName">속성명</param>
protected void FirePropertyChangedEvent([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 편집 사람 속성 변경시 처리하기 - editPerson_PropertyChanged(sender, e)
/// <summary>
/// 편집 사람 속성 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void editPerson_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
(SubmitCommand as Command).ChangeCanExecute();
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 속성 값 설정하기 - SetPropertyValue<TProperty>(field, TProperty value, [CallerMemberName] string propertyName = null)
/// <summary>
/// 속성 값 설정하기
/// </summary>
/// <typeparam name="TProperty">속성 타입</typeparam>
/// <param name="field">필드</param>
/// <param name="value">값</param>
/// <param name="propertyName">속성명</param>
/// <returns>처리 결과</returns>
private bool SetPropertyValue<TProperty>(ref TProperty field, TProperty value, [CallerMemberName] string propertyName = null)
{
if(object.Equals(field, value))
{
return false;
}
field = value;
FirePropertyChangedEvent(propertyName);
return true;
}
#endregion
#region 실행 가능 여부 변경하기 - ChangeCanExecute()
/// <summary>
/// 실행 가능 여부 변경하기
/// </summary>
private void ChangeCanExecute()
{
(NewCommand as Command).ChangeCanExecute();
(SubmitCommand as Command).ChangeCanExecute();
(CancelCommand as Command).ChangeCanExecute();
}
#endregion
}
300x250
▶ MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="TestProject.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TestProject">
<ContentPage.BindingContext>
<local:MainPageViewModel />
</ContentPage.BindingContext>
<Grid
Margin="10"
RowDefinitions="Auto,Auto,Auto,*">
<Button Grid.Row="0"
HorizontalOptions="Start"
Text="추가"
Command="{Binding NewCommand}" />
<Grid Grid.Row="1"
Margin="0,10,0,0"
IsEnabled="{Binding IsEditing}">
<Grid
Margin="10"
BindingContext="{Binding EditPerson}"
RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="Auto,*">
<Label Grid.Row="0" Grid.Column="0"
VerticalOptions="Center"
Text="성명" />
<Entry Grid.Row="0" Grid.Column="1"
VerticalOptions="Center"
Margin="10,0,0,0"
Text="{Binding Name}" />
<Label Grid.Row="1" Grid.Column="0"
VerticalOptions="Center"
Text="나이" />
<StackLayout Grid.Row="1" Grid.Column="1"
VerticalOptions="Center"
Margin="10,0,0,0"
Orientation="Horizontal">
<Stepper
VerticalOptions="Center"
Maximum="100"
Value="{Binding Age}" />
<Label
VerticalOptions="Center"
Text="{Binding Age, StringFormat='{0}세'}" />
</StackLayout>
<Label Grid.Row="2" Grid.Column="0"
VerticalOptions="Center"
Text="기술" />
<Entry Grid.Row="2" Grid.Column="1"
Margin="10,0,0,0"
Text="{Binding Skill}" />
</Grid>
</Grid>
<Grid Grid.Row="2"
Margin="20,10,20,10"
ColumnDefinitions="*,10,*">
<Button Grid.Column="0"
Text="Submit"
Command="{Binding SubmitCommand}" />
<Button Grid.Column="2"
VerticalOptions="Center"
Text="Cancel"
Command="{Binding CancelCommand}" />
VerticalOptions="Center" />
</Grid>
<ListView Grid.Row="3"
Margin="10,20,10,20"
ItemsSource="{Binding PersonList}" />
</Grid>
</ContentPage>
728x90
반응형
그리드형(광고전용)
댓글을 달아 주세요