I work in a Windows Forms application, C #, IoC ninject. As the question says, obtain data from a grandchild form to the father (from the father a child form is called and this calls another form) and from the latter the data is taken and passed to the father.
This is easy to solve using global variables, but it is bad programming practice.
What I could do is implement events under a Singleton pattern by following this link pass data between forms
Events
public static class CompleteEvent
{
public delegate void CompleteHandler(CompleteEventArgs arg);
public static event CompleteHandler Complete;
public static event CompleteHandler PasarDosVariables;
public static void RaiseEvent() { }
public static void RaiseEvent(string strValor)
{
//if (Complete != null)
// Complete(new CompleteEventArgs());
Complete?.Invoke(new CompleteEventArgs(strValor));
}
public static void RaiseEvent(int codigo, string valor)
{
PasarDosVariables?.Invoke(new CompleteEventArgs(codigo, valor));
}
}
public class CompleteEventArgs : EventArgs
{
public CompleteEventArgs() { }
public CompleteEventArgs(string strValor)
{
StrValor = strValor;
}
public CompleteEventArgs(int codigo, string valor)
{
this.Codigo = codigo;
this.StrValor = valor;
}
public int Codigo { get; set; }
public string StrValor { get; set; }
}
Collect Data
public class RecolectarDatos
{
private static RecolectarDatos _datos;
private RecolectarDatos()
{
}
public static RecolectarDatos Instance()
{
//if (_controles == null)
// _controles = new ActivarControles();
//return _controles;
return _datos ?? (_datos = new RecolectarDatos());
}
public int Codigo { get; set; }
public string StrValor { get; set; }
}
My code that gives me problems when I use the CompleteEvent.PasarDosVariables
event more than once.
private void btnBuscarColor_Click(object sender, EventArgs e)
{
var argNombreEntidad = new ConstructorArgument("nombreEntidad", StrColour.NameEntity);
var argT = new ConstructorArgument("t", EnumAsignacionTablas.Colour);
var frm = CompositionRoot.Resolve<FrmInputBox>(argNombreEntidad, argT);
CompleteEvent.PasarDosVariables -= CompleteEvent_PasarDosVariables;
CompleteEvent.PasarDosVariables += CompleteEvent_PasarDosVariables;
frm.ShowDialog();
}
private void CompleteEvent_PasarDosVariables(CompleteEventArgs arg)
{
try
{
if (vBool)
{
if (arg.Codigo != 0 && !string.IsNullOrEmpty(arg.StrValor))
{
if (DetalleItemColour.Count != 1)
{
var entity = new Colour()
{
ColourId = arg.Codigo,
Nombre = arg.StrValor
};
_detalleColour.Add(entity);
dgvColor.AutoGenerateColumns = false;
dgvColor.DataSource = DetalleItemColour;
CompleteEvent.RaiseEvent();
arg.Codigo = 0;
arg.StrValor = String.Empty;
}
else
{
MessageBoxEx.EnableGlass = false;
MessageBoxEx.Show(this, "Solo se permite un solo Color", StrColour.NameEntity,
MessageBoxButtons.OK, MessageBoxIcon.Information);
vBool = false;
arg.Codigo = 0;
arg.StrValor = String.Empty;
}
}
}
}
catch (Exception e)
{
MessageBoxEx.Show(this, $"Error:{e.Message}", "Error Inesperado", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void txtMarca_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F3)
{
var argNombreEntidad = new ConstructorArgument("nombreEntidad", StrMarca.NameEntity);
var argT = new ConstructorArgument("t", EnumAsignacionTablas.Marca);
var frm = CompositionRoot.Resolve<FrmInputBox>(argNombreEntidad, argT);
CompleteEvent.PasarDosVariables -= CompleteEvent_PasarDosVariables1;
CompleteEvent.PasarDosVariables += CompleteEvent_PasarDosVariables1;
frm.ShowDialog();
}
}
private void CompleteEvent_PasarDosVariables1(CompleteEventArgs arg)
{
if (arg.Codigo != 0 && !string.IsNullOrEmpty(arg.StrValor))
{
txtMarcaId.Text = Convert.ToString(arg.Codigo);
txtMarca.Text = arg.StrValor;
CompleteEvent.RaiseEvent();
arg.Codigo = 0;
arg.StrValor = string.Empty;
}
}
The problem is that when I use an event, the other event is activated and the data is crushed.