В настоящее время я выполняю рефакторинг своих кодов для соответствия SOLID. Принцип SOLID практикуется большинством разработчиков, и я пренебрегаю изучением этого принципа. Но сейчас мне это нужно!
Моя ViewModel содержит События, Поля, Свойства (ObseravbleCollection и другие типы данных), ICommand, Методы, которые сделаны для определенного c Представления, а некоторые из ViewModel содержат Свойства и Методы, только если коллекция будет использоваться в других видах. Так что для некоторых списков это больше похоже на виртуальную машину многократного использования. т.е. представление, где управление сотрудниками, и другое представление для перечисления сотрудников для других целей.
Я пытаюсь понять и создал простой пользовательский интерфейс входа в систему с использованием WPF, и моя ViewModel выглядит следующим образом.
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;
using UnderstandingSOLID.Models;
using UnderstandingSOLID.Services.API;
namespace UnderstandingSOLID.ViewModels
{
public class ViewModel_Login : VMBase
{
#region events
public EventHandler OnLoggedIn;
#endregion
#region vars
#endregion
#region properties
public ObservableCollection<Model_ServerType> ServerTypes { get; set; } = new ObservableCollection<Model_ServerType>();
private Model_ServerType _SelectedServerType = new Model_ServerType();
public Model_ServerType SelectedServerType
{
get { return _SelectedServerType; }
set
{
Set(nameof(SelectedServerType), ref _SelectedServerType, value);
}
}
private string _ServerName = null;
public string ServerName
{
get { return _ServerName; }
set { Set(nameof(ServerName), ref _ServerName, value); }
}
private string _Username = null;
public string Username
{
get { return _Username; }
set { Set(nameof(Username), ref _Username, value); }
}
private string _Password = null;
public string Password
{
get { return _Password; }
set { Set(nameof(Password), ref _Password, value); }
}
private bool _ShowLoginUI = false;
public bool ShowLoginUI
{
get { return _ShowLoginUI; }
set { Set(nameof(ShowLoginUI), ref _ShowLoginUI, value); }
}
#endregion
#region commands
public ICommand Command_Connect { get; set; }
public ICommand Command_Help { get; set; }
#endregion
#region ctors
public ViewModel_Login()
{
InitCommands();
// used only in UWP & WPF
// or anything that supports design time updates
if (base.IsInDesignMode)
{
DesignData();
}
}
#endregion
#region command methods
void Command_Connect_Click()
{
Connect();
}
void Command_Help_Click()
{
// does nothing at the moment
}
#endregion
#region methods
void InitCommands()
{
if (Command_Connect == null) Command_Connect = new RelayCommand(Command_Connect_Click);
if (Command_Help == null) Command_Help = new RelayCommand(Command_Help_Click);
}
/// <summary>
/// codes here are messy since they are only used for desining the UI
/// </summary>
void DesignData()
{
this.ShowLoginUI = true;
this.ServerTypes.Clear();
string[] serverTypes = new string[]
{
"Database Engine",
"Analysis Services"
};
for (int i = 0; i < serverTypes.Length; i++)
{
this.ServerTypes.Add(new Model_ServerType()
{
Id = i,
ServerType = serverTypes[i]
});
}
this.ShowDlgMsg("Title", "Failed to login");
}
// this is called in Loaded event in MainPage.xaml.cs
public async Task RefreshData()
{
this.ServerTypes.Clear();
string[] serverTypes = new string[]
{
"Database Engine",
"Analysis Services",
"Reporting Services",
"Integration Services"
};
for(int i = 0; i < serverTypes.Length; i++)
{
this.ServerTypes.Add(new Model_ServerType()
{
Id = i,
ServerType = serverTypes[i]
});
}
}
async Task Connect()
{
if(this.SelectedServerType.ServerType != null && await ApiClient.I.Login(this.Username, this.Password))
{
this.HideDlgMsg();
// navigate to main page
// but we'll just Invoke an event for simplicity
this.OnLoggedIn?.Invoke(this, null);
}
else
{
this.ShowDlgMsg("Error", "Failed to login");
}
}
#endregion
}
}
VMBase выглядит следующим образом
using GalaSoft.MvvmLight;
namespace UnderstandingSOLID.ViewModels
{
public abstract class VMBase : ViewModelBase
{
private bool _ShowMessage = false;
public bool ShowMessage
{
get { return _ShowMessage; }
set { Set(nameof(ShowMessage), ref _ShowMessage, value); }
}
private string _MessageTitle = null;
public string MessageTitle
{
get { return _MessageTitle; }
set { Set(nameof(MessageTitle), ref _MessageTitle, value); }
}
private string _MessageBody = null;
public string MessageBody
{
get { return _MessageBody; }
set { Set(nameof(MessageBody), ref _MessageBody, value); }
}
public virtual void ShowDlgMsg(string title, string message)
{
this.ShowMessage = true;
this.MessageTitle = title;
this.MessageBody = message;
}
public void HideDlgMsg()
{
this.ShowMessage = false;
}
}
}
Так я обычно пишу всем членам моей ViewModel. Не обращайте внимания на то, как я вызывал метод Login in Connect в ViewModel_Login. Это было только упрощено.
Так как же реализовать принцип SOLID в этом случае?
Пример приложения для входа в систему выглядит так в простое ![enter image description here](https://i.stack.imgur.com/rO3Jy.png)
Не удалось войти в систему ![enter image description here](https://i.stack.imgur.com/1K9Yk.png)
вошли в систему ![enter image description here](https://i.stack.imgur.com/wNygm.png)
Скачать репо можно здесь https://github.com/Nullstr1ng/UnderstandingSOLID