Hi friends!
for my classes i have a base class called DomaiObject, wich implements INotifyPropertyChanged and IDataErrorInfo. Its based on implementation i saw in
www.codeproject.com.
Problem is, properties are being saved with a 'string.empty" and not with value in TextBox.
My base class also implements a Rule mechanism, wich exposes a "IsValid" property. Here is code for my base class:
Code:
[Serializable()]
public abstract class DomainObject:
INotifyPropertyChanged,
IDataErrorInfo {
private List<Rule> _rules;
/// <summary>
/// Constructor.
/// </summary>
public DomainObject() {
}
/// <summary>
/// Indica o objeto é válido ou não.
/// </summary>
public virtual bool IsValid {
get {
return this.Error == null;
}
}
/// <summary>
/// Retorna uma mensagem de erro indicando o que está errado com o objeto. O padrão é uma string vazia ("").
/// </summary>
public virtual string Error {
get {
string result = this[string.Empty];
if (result != null && result.Trim().Length == 0) {
result = null;
}
return result;
}
}
/// <summary>
/// Retorna a mesnagem de erro para a propriedade com o nome especificado.
/// </summary>
/// <param name="propertyName">O nome da propriedade que se deseja objer o erro.</param>
/// <returns>A mensagem de erro para a propriedade. O padrão é uma string vazia ("").</returns>
public virtual string this[string propertyName] {
get {
string result = string.Empty;
propertyName = CleanString(propertyName);
foreach (Rule r in GetBrokenRules(propertyName)) {
if (propertyName == string.Empty || r.PropertyName == propertyName) {
result += r.Description;
result += Environment.NewLine;
}
}
result = result.Trim();
if (result.Length == 0) {
result = null;
}
return result;
}
}
/// <summary>
/// Valida todas as regras para o objeto, retornando a lista de erros.
/// </summary>
/// <returns>Uma coleção, somente-leitura, das regras que foram quebradas.</returns>
public virtual ReadOnlyCollection<Rule> GetBrokenRules() {
return GetBrokenRules(string.Empty);
}
/// <summary>
/// Valida todas as regras associadas ao nome da propriedade passada, retornando uma lista das regras quebradas.
/// </summary>
/// <param name="property">O nome da propriedade a ser verificada. Se for null ou vazio, todas regras serão validadas.</param>
/// <returns>Uma coleção, somente-leitura, das regras que foram quebradas.</returns>
public virtual ReadOnlyCollection<Rule> GetBrokenRules(string property) {
property = CleanString(property);
// Se as regras não foram criadas, cria agora.
if (_rules == null) {
_rules = new List<Rule>();
_rules.AddRange(this.CreateRules());
}
List<Rule> broken = new List<Rule>();
foreach (Rule r in this._rules) {
// Assegura a validação de apenas uma regra
if (r.PropertyName == property || property == string.Empty) {
bool isRuleBroken = !r.ValidateRule(this);
Debug.WriteLine(DateTime.Now.ToLongTimeString() + ": Validando a regra: '" + r.ToString() + "' no objeto '" + this.ToString() + "'. Resultado = " + ((isRuleBroken == false) ? "Válido" : "Violado"));
if (isRuleBroken) {
broken.Add(r);
}
}
}
return broken.AsReadOnly();
}
/// <summary>
/// Ocorre quando qualquer propriedade é alterada.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Faça um Override deste método para criar suas próprias regras para validar o objeto. Estas regras devem ser validadas antes
/// que o objeto possa ser considerado válido para ser salvo.
/// </summary>
/// <returns>Uma coleção das regras a serem adicionadas para o objeto.</returns>
protected virtual List<Rule> CreateRules() {
return new List<Rule>();
}
/// <summary>
/// Um método helper que dispara o evento PropertyChanged para uma propriedade
/// </summary>
/// <param name="propertyNames">Os nomes das propriedades que sofreram alterações.</param>
protected virtual void NotifyChanged(params string[] propertyNames) {
foreach (string name in propertyNames) {
OnPropertyChanged(new PropertyChangedEventArgs(name));
}
OnPropertyChanged(new PropertyChangedEventArgs("IsValid"));
}
/// <summary>
/// Limpa uma string assegurando que não é nula e retira os espaços em branco desnecessários.
/// </summary>
/// <param name="s">String a ser limpa.</param>
protected string CleanString(string s) {
return (s ?? string.Empty).Trim();
}
/// <summary>
/// Dispara o evento PropertyChanged.
/// </summary>
/// <param name="e">Event arguments.</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, e);
}
}
}
and here i show how i do in my windows form
Code:
session = NHibernateSessionFactory.OpenSession();
edificio = new TEdificio();
edificioBinding.DataSource = edificio;
txtNome.Focus();
try
{
trans = session.BeginTransaction();
session.SaveOrUpdate(edificio);
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
finally
{
}
As you see, the propery "Nome" is binded to a TextBox.Text property. But i dont get value of TextBox.Text persisted, i get always an empty string. To turn around this i do before SaveOrUpdate:
Code:
[b]edificio.Nome = txtNome.Text;[/b]
session.SaveOrUpdate(edificio);
trans.Commit();
This way things get right. But the point is, if i make use of databinding i donw wanna set my classes properties programmatically.... so, what i´m doing wrong ?
Thanks !!!!!