2021-04-01 21:30:29 +04:00
using DesktopTools.BaseControls ;
using DesktopTools.Enums ;
using DesktopTools.Helpers ;
using DesktopTools.Interfaces ;
using DesktopTools.Models ;
using ModuleTools.Attributes ;
using ModuleTools.BindingModels ;
using ModuleTools.BusinessLogics ;
using ModuleTools.Enums ;
using ModuleTools.Extensions ;
using ModuleTools.ViewModels ;
using System ;
using System.Linq ;
using System.Reflection ;
2021-04-14 13:47:48 +04:00
using System.Threading.Tasks ;
2021-04-01 21:30:29 +04:00
using System.Windows.Forms ;
2021-04-02 09:29:09 +04:00
using System.Xml.Linq ;
2021-04-01 21:30:29 +04:00
namespace DesktopTools.Controls
{
public partial class GenericControlEntityElement < G , S , L , E , BL > : MainControlViewEntityElement , IControlViewEntityElement
where G : GetBindingModel , new ( )
where S : SetBindingModel , new ( )
where L : ListViewModel < E >
where E : ElementViewModel
where BL : GenericBusinessLogic < G , S , L , E >
{
/// <summary>
/// Объект бизнес-логики для получения данных
/// </summary>
2021-04-11 20:49:26 +04:00
protected readonly BL _businessLogic ;
2021-04-01 21:30:29 +04:00
/// <summary>
/// Методы для реализации в generic-контроле
/// </summary>
protected IGenericControlEntityElement _genericControlViewEntityElement ;
/// <summary>
/// Признак налиичия изменений
/// </summary>
private bool _haveChages = false ;
/// <summary>
/// Ширина контрола по умолчанию
/// </summary>
private readonly int _defaultControlWidth = 350 ;
2021-04-11 20:49:26 +04:00
protected E _element = null ;
2021-04-01 21:30:29 +04:00
/// <summary>
/// Событие, вызываемое при закрытии контрола
/// </summary>
private event Action < Guid > CloseElementEvent ;
2021-04-02 09:29:09 +04:00
/// <summary>
/// События установки одинаковой ширины для заголовков контролов
/// </summary>
2021-04-01 21:30:29 +04:00
private event Action < int > SetTitleWidth ;
2021-04-02 09:29:09 +04:00
/// <summary>
/// Событие установки значения
/// </summary>
2021-04-01 21:30:29 +04:00
private event Action < object > SetValues ;
2021-04-02 09:29:09 +04:00
/// <summary>
/// Событие с б р о с а значения в исходное состояние
/// </summary>
2021-04-01 21:30:29 +04:00
private event Action DropValues ;
2021-04-02 09:29:09 +04:00
/// <summary>
/// Событие проверки заполненности контрола
/// </summary>
2021-04-01 21:30:29 +04:00
private event Func < bool > CheckValues ;
2021-04-02 09:29:09 +04:00
/// <summary>
/// Событие получения значения из контрола
/// </summary>
2021-04-01 21:30:29 +04:00
private event Action < object > GetValues ;
private E Element
{
get { return _element ; }
set
{
try
{
_element = value ;
2021-04-03 10:50:51 +04:00
if ( _element ! = null )
2021-04-01 21:30:29 +04:00
{
2021-04-03 10:50:51 +04:00
SetValues ? . Invoke ( _element ) ;
if ( tabControl . Visible )
2021-04-01 21:30:29 +04:00
{
2021-04-03 10:50:51 +04:00
foreach ( TabPage page in tabControl . TabPages )
2021-04-01 21:30:29 +04:00
{
2021-04-03 10:50:51 +04:00
if ( page . Name = = tabPageMain . Name )
{
continue ;
}
if ( page . Controls [ 0 ] is IControlChildEntity cntrl )
{
cntrl . ParentId = _element . Id ;
cntrl . Open ( new ControlOpenModel { OpenMode = ControlOpenMode . Child } ) ;
}
2021-04-01 21:30:29 +04:00
}
}
}
_haveChages = false ;
}
catch ( Exception ex )
{
2021-04-03 10:47:31 +04:00
DialogHelper . MessageException ( ex . Message , $"{Title}. Ошибка при установки значений" ) ;
2021-04-01 21:30:29 +04:00
}
}
}
public GenericControlEntityElement ( )
{
InitializeComponent ( ) ;
InitEvents ( ) ;
_businessLogic = DependencyManager . Instance . Resolve < BL > ( ) ;
_controlViewEntityElement = this ;
}
2021-04-14 13:47:48 +04:00
public async void OpenControl ( ControlOpenModel model )
2021-04-01 21:30:29 +04:00
{
if ( model . CloseElement ! = null )
{
CloseElementEvent + = model . CloseElement ;
}
if ( panelContainer . Controls . Count = = 0 )
{
try
{
2021-04-08 10:37:47 +04:00
Configurate ( GetConfig ( ) ) ;
2021-04-01 21:30:29 +04:00
}
catch ( Exception ex )
{
2021-04-03 10:47:31 +04:00
DialogHelper . MessageException ( ex . Message , $"{Title}. Ошибка при конфигурации" ) ;
2021-04-01 21:30:29 +04:00
}
}
if ( model . ElementId . HasValue )
{
2021-04-14 13:47:48 +04:00
Element = await _businessLogic . GetElementAsync ( new G { Id = model . ElementId } ) ;
2021-04-01 21:30:29 +04:00
if ( Element = = null )
{
2021-04-03 10:47:31 +04:00
DialogHelper . MessageException ( _businessLogic . Errors , $"{Title}. Ошибки при получении элемента" ) ;
2021-04-01 21:30:29 +04:00
}
}
Dock = DockStyle . Fill ;
}
2021-04-02 09:29:09 +04:00
public IControl GetInstanceControl ( ) = > _genericControlViewEntityElement ? . GetInstanceGenericControl ( ) ;
public string SaveControlToXml ( ) = > new XElement ( "Control" ,
new XAttribute ( "Type" , GetType ( ) . FullName ) ,
new XAttribute ( "ControlId" , ControlId ) ,
new XAttribute ( "Title" , Title ) ) . ToString ( ) ;
public void LoadControlFromXml ( string xml )
{
var control = XElement . Parse ( xml ) . Element ( "Control" ) ;
ControlId = new Guid ( control . Attribute ( "ControlId" ) . Value . ToString ( ) ) ;
Title = control . Attribute ( "Title" ) . Value . ToString ( ) ;
}
2021-04-01 21:30:29 +04:00
private void InitEvents ( )
{
2021-04-14 13:47:48 +04:00
toolStripButtonSave . Click + = async ( object sender , EventArgs e ) = > { await SaveAsync ( ) ; } ;
2021-04-01 21:30:29 +04:00
toolStripButtonReload . Click + = ( object sender , EventArgs e ) = >
{
if ( DialogHelper . MessageQuestion ( "Отменить все внесенные изменения?" ) = = DialogResult . Yes )
{
try
{
DropValues ? . Invoke ( ) ;
}
catch ( Exception ex )
{
2021-04-03 10:47:31 +04:00
DialogHelper . MessageException ( ex . Message , $"{Title}. Ошибка при с б р о с е значений" ) ;
2021-04-01 21:30:29 +04:00
}
}
} ;
2021-04-14 13:47:48 +04:00
toolStripButtonClose . Click + = async ( object sender , EventArgs e ) = >
2021-04-08 14:13:35 +04:00
{
2021-04-01 21:30:29 +04:00
if ( _haveChages & & DialogHelper . MessageQuestion ( "Имеется несохраненные данные, вы действительно хотите закрыть элемент?" , "Закрытие элемента" ) = = DialogResult . Yes )
{
2021-04-14 13:47:48 +04:00
if ( ! ( await SaveAsync ( ) ) )
2021-04-01 21:30:29 +04:00
{
return ;
}
}
CloseElementEvent ? . Invoke ( ControlId ) ;
Dispose ( ) ;
} ;
}
2021-04-08 10:37:47 +04:00
private void Configurate ( ControlViewEntityElementConfiguration config )
2021-04-01 21:30:29 +04:00
{
2021-04-08 10:37:47 +04:00
// Загрузка подпунктов в контекстное меню и в пункт меню "Действие"
if ( config . ControlOnMoveElem ! = null )
{
foreach ( var elem in config . ControlOnMoveElem )
{
ToolStripMenuItem item = new ( ) { Text = elem . Value . Title , Name = elem . Key } ;
item . Click + = elem . Value . Event ;
toolStripSplitButtonActions . DropDownItems . Add ( item ) ;
2021-04-08 14:13:35 +04:00
ToolStripMenuItem itemContext = new ( ) { Text = elem . Value . Title , Name = elem . Key } ;
itemContext . Click + = elem . Value . Event ;
contextMenuStripElement . Items . Add ( itemContext ) ;
2021-04-08 10:37:47 +04:00
}
}
// либо скрытие пункта, если не предусмотренно подпунктов
else
{
toolStripSplitButtonActions . Visible = false ;
toolStripSeparator1 . Visible = false ;
}
2021-04-01 21:30:29 +04:00
var attributeClass = typeof ( E ) . GetCustomAttribute < ViewModelControlElementClassAttribute > ( ) ;
if ( attributeClass = = null )
{
return ;
}
tabControl . Visible = attributeClass . HaveDependenceEntities ;
panelContainer . Visible = ! attributeClass . HaveDependenceEntities ;
Width = attributeClass . Width ! = 0 ? attributeClass . Width : _defaultControlWidth ;
int positionY = 5 ;
int positionX = 5 ;
int interval = 15 ;
int titleWidth = 0 ;
foreach ( var property in typeof ( E ) . GetProperties ( ) )
{
var attribute = property . GetCustomAttribute < ViewModelControlElementPropertyAttribute > ( ) ;
if ( attribute ! = null )
{
AbstractBaseControl control = null ;
switch ( attribute . ControlType )
{
case ControlType . ControlString :
control = new BaseControlString ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . MaxLength ) ;
break ;
case ControlType . ControlText :
control = new BaseControlText ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . MaxLength , attribute . Height ) ;
break ;
case ControlType . ControlInt :
control = new BaseControlInt ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . MinValue , attribute . MaxValue ) ;
break ;
case ControlType . ControlDecimal :
control = new BaseControlDecimal ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . MinValue ,
attribute . MaxValue , attribute . DecimalPlaces ) ;
break ;
case ControlType . ControlBool :
control = new BaseControlBool ( property . Name , attribute . MustHaveValue , attribute . ReadOnly ) ;
break ;
case ControlType . ControlDateTime :
control = new BaseControlDateTime ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . MinDate ,
attribute . MaxDate , attribute . CustomDateFormat ) ;
break ;
case ControlType . ControlImage :
control = new BaseControlImage ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , attribute . Width , attribute . Height ) ;
break ;
case ControlType . ControlEnum :
control = new BaseControlEnum ( property . Name , attribute . MustHaveValue , attribute . ReadOnly , property . PropertyType ) ;
break ;
case ControlType . ControlGuid :
2021-04-02 16:06:12 +04:00
if ( attribute . ControlTypeObject . IsNotEmpty ( ) & & Type . GetType ( attribute . ControlTypeObject ) ! = null )
2021-04-01 21:30:29 +04:00
{
control = new BaseControlGuid ( property . Name , attribute . MustHaveValue , attribute . ReadOnly ,
2021-04-08 14:13:35 +04:00
DependencyManager . Instance . Resolve ( Type . GetType ( attribute . ControlTypeObject ) ) as IControlEntitySelectable ,
2021-04-01 21:30:29 +04:00
property . Name = = ParentPropertyName ? ParentId : null ) ;
}
break ;
}
if ( control = = null )
{
continue ;
}
var widthTitle = control . SetTitle ( attribute . DisplayName ) ;
if ( widthTitle > titleWidth )
{
titleWidth = widthTitle ;
}
control . OnValueChangeEvent + = ( ) = > { _haveChages = true ; } ;
SetValues + = control . SetValue ;
DropValues + = control . DropValue ;
CheckValues + = control . CheckValue ;
SetTitleWidth + = control . SetTitleWidth ;
GetValues + = control . GetValue ;
control . Location = new System . Drawing . Point ( positionX , positionY ) ;
control . Width = Width - positionX * 2 - ( tabControl . Visible ? 10 : 0 ) ;
control . Anchor = AnchorStyles . Top | AnchorStyles . Left ;
if ( panelContainer . Visible )
{
control . Anchor | = AnchorStyles . Right ;
}
positionY + = control . Height + interval ;
if ( panelContainer . Visible )
{
panelContainer . Controls . Add ( control ) ;
}
if ( tabControl . Visible )
{
tabPageMain . Controls . Add ( control ) ;
}
}
}
SetTitleWidth ( titleWidth ) ;
Height = attributeClass . Height ! = 0 ? attributeClass . Height : positionY ;
if ( attributeClass . HaveDependenceEntities )
{
var attrDependences = typeof ( E ) . GetCustomAttributes < ViewModelControlElementDependenceEntityAttribute > ( ) ;
if ( attrDependences ! = null )
{
foreach ( var attr in attrDependences )
{
if ( DependencyManager . Instance . Resolve ( Type . GetType ( attr . ControlTypeObject ) ) is IControlChildEntity control )
{
var cntrl = control . GetInstance ( ) as IControlChildEntity ;
cntrl . ParentPropertyName = attr . ParentPropertyName ;
//cntrl.Open(null);
var tabPage = new TabPage
{
Location = new System . Drawing . Point ( 4 , 24 ) ,
Name = "tabPage" ,
Padding = new Padding ( 3 ) ,
Size = new System . Drawing . Size ( 122 , 99 ) ,
TabIndex = 0 ,
Text = attr . Title ,
UseVisualStyleBackColor = true
} ;
tabPage . Controls . Add ( cntrl as UserControl ) ;
tabControl . TabPages . Add ( tabPage ) ;
if ( attr . IsActive )
{
tabPage . Select ( ) ;
}
}
}
}
}
}
2021-04-14 13:47:48 +04:00
private async Task < bool > SaveAsync ( )
2021-04-01 21:30:29 +04:00
{
if ( CheckValues . GetInvocationList ( ) . Select ( x = > ( bool ) x . DynamicInvoke ( ) ) . ToList ( ) . Any ( x = > ! x ) )
{
return false ;
}
var model = Element = = null ? new S ( ) : Mapper . MapToClass < E , S > ( Element , true ) ;
try
{
GetValues ( model ) ;
}
catch ( Exception ex )
{
DialogHelper . MessageException ( ex . Message , "Ошибка при получении значений" ) ;
}
if ( model ! = null )
{
if ( Element = = null )
{
2021-04-14 13:47:48 +04:00
Element = await _businessLogic . CreateAsync ( model ) ;
2021-04-01 21:30:29 +04:00
}
else
{
2021-04-14 13:47:48 +04:00
Element = await _businessLogic . UpdateAsync ( model ) ;
2021-04-01 21:30:29 +04:00
}
if ( Element = = null )
{
DialogHelper . MessageException ( _businessLogic . Errors , "Ошибки при сохранении элемента" ) ;
2021-04-03 10:52:22 +04:00
return false ;
2021-04-01 21:30:29 +04:00
}
_haveChages = false ;
DialogHelper . MessageInformation ( "Сохранение прошло успешно" , "Сообщение" ) ;
return true ;
}
return false ;
}
2021-04-08 10:37:47 +04:00
private ControlViewEntityElementConfiguration GetConfig ( ) = > _genericControlViewEntityElement ? . GetConfigControl ( ) ;
2021-04-08 14:13:35 +04:00
protected bool FillModel ( S model )
{
if ( CheckValues . GetInvocationList ( ) . Select ( x = > ( bool ) x . DynamicInvoke ( ) ) . ToList ( ) . Any ( x = > ! x ) )
{
return false ;
}
try
{
GetValues ( model ) ;
return true ;
}
catch ( Exception ex )
{
DialogHelper . MessageException ( ex . Message , "Ошибка при получении значений" ) ;
}
return false ;
}
2021-04-01 21:30:29 +04:00
}
}