From 3d216dfe8359a48d5a64fa58e744c5640f5bedc2 Mon Sep 17 00:00:00 2001 From: syneffort Date: Fri, 19 Apr 2024 10:21:08 +0900 Subject: [PATCH] mvvm event driven --- .../Converters/BoolToVisibilityConverter.cs | 35 +++++ MVVMwithWPF/MVVMwithWPF/Models/Member.cs | 28 ++++ .../MVVMwithWPF/ViewModels/MainViewModel.cs | 135 +++++++++++++++++- .../MVVMwithWPF/ViewModels/ViewModelBase.cs | 8 +- MVVMwithWPF/MVVMwithWPF/Views/MainWindow.xaml | 132 +++++++++++++++++ 5 files changed, 330 insertions(+), 8 deletions(-) create mode 100644 MVVMwithWPF/MVVMwithWPF/Converters/BoolToVisibilityConverter.cs create mode 100644 MVVMwithWPF/MVVMwithWPF/Models/Member.cs diff --git a/MVVMwithWPF/MVVMwithWPF/Converters/BoolToVisibilityConverter.cs b/MVVMwithWPF/MVVMwithWPF/Converters/BoolToVisibilityConverter.cs new file mode 100644 index 0000000..e99d00b --- /dev/null +++ b/MVVMwithWPF/MVVMwithWPF/Converters/BoolToVisibilityConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace MVVMwithWPF.Converters +{ + internal class BoolToVisibilityConverter : IValueConverter + { + public Visibility TrueVlaue { get; set; } = Visibility.Visible; + public Visibility FalseValue { get; set; } = Visibility.Collapsed; + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is bool boolVlaue) + { + if (boolVlaue) + return TrueVlaue; + else + return FalseValue; + } + + return Binding.DoNothing; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/MVVMwithWPF/MVVMwithWPF/Models/Member.cs b/MVVMwithWPF/MVVMwithWPF/Models/Member.cs new file mode 100644 index 0000000..1fe77b8 --- /dev/null +++ b/MVVMwithWPF/MVVMwithWPF/Models/Member.cs @@ -0,0 +1,28 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MVVMwithWPF.Models +{ + internal partial class Member : ObservableObject, ICloneable + { + public int Id { get; set; } + public DateTime RegDate { get; set; } + + [ObservableProperty] + private string _name; + [ObservableProperty] + private string _phone; + [ObservableProperty] + private bool _isUse; + + + public object Clone() + { + return MemberwiseClone(); + } + } +} diff --git a/MVVMwithWPF/MVVMwithWPF/ViewModels/MainViewModel.cs b/MVVMwithWPF/MVVMwithWPF/ViewModels/MainViewModel.cs index 822a452..c84cd7b 100644 --- a/MVVMwithWPF/MVVMwithWPF/ViewModels/MainViewModel.cs +++ b/MVVMwithWPF/MVVMwithWPF/ViewModels/MainViewModel.cs @@ -1,16 +1,147 @@ -using System; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using MVVMwithWPF.Models; +using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; namespace MVVMwithWPF.ViewModels { - internal class MainViewModel : ViewModelBase + internal partial class MainViewModel : ViewModelBase { + [ObservableProperty] + private ObservableCollection _members; + [ObservableProperty] + private bool _isEditing; + [ObservableProperty] + private Member _editMember; + + private bool CanEditMember { get { return EditMember != null; } } + public MainViewModel() { Title = "Main View"; + Init(); + } + + private void Init() + { + Members = new ObservableCollection(); + { + new Member() + { + Id = 1, + Name = "member001", + Phone = "010-1234-5678", + RegDate = DateTime.Now, + IsUse = true + }; + }; + + PropertyChanged += MainViewModel_PropertyChanged; + } + + [RelayCommand] + private void Save() + { + IsEditing = false; + if (EditMember.Id == 0) + { + var id = Members.Any() ? Members.Max(m => m.Id) + 1 : 1; + EditMember.Id = id; + EditMember.RegDate = DateTime.Now; + + Members.Add((Member)EditMember.Clone()); + + EditMember = null; + } + else + { + var member = Members.FirstOrDefault(m => m.Id == EditMember.Id); + if (member == null) + return; + + member.Name = EditMember.Name; + member.Phone = EditMember.Phone; + member.IsUse = EditMember.IsUse; + } + } + + [RelayCommand] + private void Cancle() + { + IsEditing = false; + EditMember = null; + } + + [RelayCommand(CanExecute = nameof(CanEditMember))] + private void Delete() + { + if (EditMember == null) + return; + + var result = MessageBox.Show("선택된 아이템을 삭제하시겠습니까?", "확인", MessageBoxButton.YesNo); + if (result != MessageBoxResult.Yes) + return; + + IsEditing = false; + var removeMember = Members.FirstOrDefault(m => m.Id == EditMember.Id); + if (removeMember != null) + Members.Remove(removeMember); + + EditMember = null; + } + + [RelayCommand] + private void New() + { + IsEditing = true; + EditMember = new Member + { + IsUse = true + }; + } + + + [RelayCommand(CanExecute = nameof(CanEditMember))] + + private void Edit() + { + IsEditing = true; + } + + [RelayCommand] + private void SelectionChanged(object param) + { + var args = param as SelectionChangedEventArgs; + if (args == null) + return; + + if (args.AddedItems.Count < 1) + { + EditMember = null; + return; + } + + if (args.AddedItems[0] is Member member) + EditMember = (Member)member.Clone(); + } + + private void MainViewModel_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + switch(e.PropertyName) + { + case nameof(EditMember): + EditCommand.NotifyCanExecuteChanged(); + DeleteCommand.NotifyCanExecuteChanged(); + break; + } } } } diff --git a/MVVMwithWPF/MVVMwithWPF/ViewModels/ViewModelBase.cs b/MVVMwithWPF/MVVMwithWPF/ViewModels/ViewModelBase.cs index 31de03f..e7dc928 100644 --- a/MVVMwithWPF/MVVMwithWPF/ViewModels/ViewModelBase.cs +++ b/MVVMwithWPF/MVVMwithWPF/ViewModels/ViewModelBase.cs @@ -7,13 +7,9 @@ using System.Threading.Tasks; namespace MVVMwithWPF.ViewModels { - internal abstract class ViewModelBase : ObservableObject + internal abstract partial class ViewModelBase : ObservableObject { + [ObservableProperty] private string _title; - public string Title - { - get => _title; - set => SetProperty(ref _title, value); - } } } diff --git a/MVVMwithWPF/MVVMwithWPF/Views/MainWindow.xaml b/MVVMwithWPF/MVVMwithWPF/Views/MainWindow.xaml index b18363f..24bccd2 100644 --- a/MVVMwithWPF/MVVMwithWPF/Views/MainWindow.xaml +++ b/MVVMwithWPF/MVVMwithWPF/Views/MainWindow.xaml @@ -1,6 +1,8 @@  + + + + + @@ -21,5 +29,129 @@ + + + + + + + + + +