첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
0.15MB

▶ 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
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요