Yes. Use [Column]
:
[Column("Código Cliente")]
public int ClienteId { get; set; }
[Column("Data de Nascimento")]
public DateTime DataNascimento { get; set; }
The title of the question should be "How to filter in Winforms by the name of the displayed column". I made a simulation and soon I must edit this answer and put the example in a chapter of Coding Craft because I inadvertently did a tutorial on how to use Entity Framework with Windows Forms and PostgreSQL.
Let's ask the questions:
Is there any way to find the information in postgresql by nickname? but without using alias, just in the field register in the table do I already enter the real name for the field?
No. You need to pass the same column name. What you can do is the user interface display the friendly column name and the code receive the column name as it actually is.
I would like to create a generic class that works for any table, thus putting the field name as a filter.
This involves using a lot Reflection . Using the "field name" is not a good idea, but you can display the field name and get another value.
To illustrate, I'll give you a complete example.
Model and Screen
I've modeled a Cliente
class as an example like this:
public class Cliente
{
[Key]
[DisplayName("Identificador do Cliente")]
public Guid ClienteId { get; set; }
[Required]
[DisplayName("Nome do Cliente")]
public String Nome { get; set; }
[Required]
[DisplayName("Nome Fantasia")]
public String Fantasia { get; set; }
}
That is, each property of the Cliente
class has an attribute [DisplayName]
". This attribute will be what I'm going to display to the user.
Once you've done this, I can make the following code to popular make up "Search Fields":
var camposPesquisa = typeof(Cliente).GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
.Select(p => new {
Valor = p.Name,
Texto = p.GetCustomAttribute<DisplayNameAttribute>().DisplayName
}).ToList();
comboBoxCampoPesquisa.ValueMember = "Valor";
comboBoxCampoPesquisa.DisplayMember = "Texto";
comboBoxCampoPesquisa.DataSource = camposPesquisa;
That is, my screen will display the values of [DisplayName]
, but the values that will go to the code are the names of my fields:
IcandothesamethingfortheconditionbysettingaEnum
Condicao
andputtingattributes [Display]
in them:
public enum Condicao
{
[Display(Name = "Igual")]
Igual,
[Display(Name = "Diferente")]
Diferente,
[Display(Name = "Maior")]
Maior,
[Display(Name = "Menor")]
Menor,
[Display(Name = "Maior ou Igual")]
MaiorOuIgual,
[Display(Name = "Menor ou Igual")]
MenorOuIgual
}
To extract the attribute from Enums
, you will need an extension method:
public static class EnumExtensions
{
public static TAttribute GetAttribute<TAttribute>(this Enum enumValue)
where TAttribute : Attribute
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<TAttribute>();
}
}
To use it like this:
var condicoes = Enum.GetValues(typeof(Condicao))
.Cast<Condicao>()
.Select(c => new
{
Valor = c.ToString(),
Texto = c.GetAttribute<DisplayAttribute>().Name
})
.ToList();
comboBoxCondicao.ValueMember = "Valor";
comboBoxCondicao.DisplayMember = "Texto";
comboBoxCondicao.DataSource = condicoes;
And then:
Grid
I'massumingGridinitializationisdoneintheOnLoad
eventofyourForm
protectedoverridevoidOnLoad(EventArgse){base.OnLoad(e);context.Clientes.Load();clienteBindingSource.DataSource=context.Clientes.Local.ToBindingList();...}
OnlywiththisIhavethedatasearchanddueobservationbythemthroughthecontextoftheEntityFramework.Thatdone,IneedtoputaCheckBox
andaneventsothatittriggersthefilteringattheappropriatetime:
privatevoidcheckBoxFiltrar_CheckedChanged(objectsender,EventArgse){Filtrar(checkBoxFiltrar.Checked);}
Justasatest,Ididthefilteringbynameasfollows:
protectedvoidFiltrar(boolcheckFiltrar){if(checkFiltrar)clienteBindingSource.DataSource=context.Clientes.Where(c=>c.Nome==textBoxValor.Text).ToList();elseclienteBindingSource.DataSource=context.Clientes.Local.ToBindingList();dataGridView.Refresh();}
Hereisthestartingpointforamorerobustlogic.Therearetwowaystodothis:byusingthe System.Linq.Dynamic library or by mounting Expressions
. For this answer I will use the first one (which basically does the same thing as the second).
Dynamic Predicates
Let's just build the dynamic predicate for Condicao.Igual
:
protected void Filtrar(bool checkFiltrar)
{
if (checkFiltrar)
// clienteBindingSource.DataSource = context.Clientes.Where(c => c.Nome == textBoxValor.Text).ToList();
clienteBindingSource.DataSource = context.Clientes
.Where(comboBoxCampoPesquisa.SelectedValue.ToString() + " == @0", textBoxValor.Text)
.ToList();
else
clienteBindingSource.DataSource = context.Clientes.Local.ToBindingList();
dataGridView.Refresh();
}
Checking if it works:
Finally,sinceIwanttosearchnotfortheexacttext,butforapartofit,Icandothefollowing:
protectedvoidFiltrar(boolcheckFiltrar){if(checkFiltrar)//clienteBindingSource.DataSource=context.Clientes.Where(c=>c.Nome==textBoxValor.Text).ToList();clienteBindingSource.DataSource=context.Clientes//.Where(comboBoxCampoPesquisa.SelectedValue.ToString()+" == @0", textBoxValor.Text)
.Where(comboBoxCampoPesquisa.SelectedValue.ToString() + ".Contains(@0)", textBoxValor.Text)
.ToList();
else
clienteBindingSource.DataSource = context.Clientes.Local.ToBindingList();
dataGridView.Refresh();
}
Converting Enum
to a String
operator stays as a homework.