Below is my base entity class. I have a class (GuidPOCO) that
inherits from BindableObject and just implements an Id property as a
guid along with some vaidation logic.
/// <summary>
/// Implements the INotifyPropertyChanged interface and
/// exposes a NotifyPropertyChanged method for derived
/// classes to raise the PropertyChange event. The event
/// arguments created by this class are cached to prevent
/// managed heap fragmentation.
/// </summary>
[Serializable]
public abstract class BindableObject : INotifyPropertyChanged,
IEditableObject, IDataErrorInfo
{
#region Data
private static readonly Dictionary<string,
PropertyChangedEventArgs> eventArgCache;
private const string ERROR_MSG = "{0} is not a public property
of {1}";
private static readonly object syncLock = new object();
private HybridDictionary oldState;
#endregion // Data
#region Constructors
static BindableObject()
{
eventArgCache = new Dictionary<string,
PropertyChangedEventArgs>();
}
protected BindableObject()
{
}
#endregion // Constructors
#region Public Members
/// <summary>
/// Raised when a public property of this object is set.
/// </summary>
[field: NonSerialized]
public virtual event PropertyChangedEventHandler
PropertyChanged;
/// <summary>
/// Returns an instance of PropertyChangedEventArgs for
/// the specified property name.
/// </summary>
/// <param name="propertyName">
/// The name of the property to create event args for.
/// </param>
public static PropertyChangedEventArgs
GetPropertyChangedEventArgs(string propertyName)
{
if (String.IsNullOrEmpty(propertyName))
throw new ArgumentException("propertyName cannot be
null or empty.");
PropertyChangedEventArgs args;
lock (BindableObject.syncLock)
{
if (!eventArgCache.TryGetValue(propertyName, out
args))
{
eventArgCache.Add(propertyName, args = new
PropertyChangedEventArgs(propertyName));
}
}
return args;
}
public abstract bool IsPropertyValid { get; }
public abstract bool IsValid { get; }
public abstract string ValidationErrors { get; }
#endregion // Public Members
#region Protected Members
/// <summary>
/// Derived classes can override this method to
/// execute logic after a property is set. The
/// base implementation does nothing.
/// </summary>
/// <param name="propertyName">
/// The property which was changed.
/// </param>
protected virtual void AfterPropertyChanged(string
propertyName)
{
}
/// <summary>
/// Attempts to raise the PropertyChanged event, and
/// invokes the virtual AfterPropertyChanged method,
/// regardless of whether the event was raised or not.
/// </summary>
/// <param name="propertyName">
/// The property which was changed.
/// </param>
protected virtual void NotifyPropertyChanged(string
propertyName)
{
this.VerifyProperty(propertyName);
PropertyChangedEventHandler handler =
this.PropertyChanged;
if (handler != null)
{
// Get the cached event args.
PropertyChangedEventArgs args =
GetPropertyChangedEventArgs(propertyName);
// Raise the PropertyChanged event.
handler(this, args);
}
this.AfterPropertyChanged(propertyName);
}
#endregion // Protected Members
#region Private Helpers
[Conditional("DEBUG")]
private void VerifyProperty(string propertyName)
{
// Thanks to Rama Krishna Vavilala for the tip to use
TypeDescriptor here, instead of manual
// reflection, so that custom properties are honored too.
//
http://www.codeproject.com/KB/WPF/podder1.aspx?msg=2381272#xx2381272xx
bool propertyExists = TypeDescriptor.GetProperties
(this).Find(propertyName, false) != null;
if (!propertyExists)
{
// The property could not be found,
// so alert the developer of the problem.
string msg = string.Format(
ERROR_MSG,
propertyName,
this.GetType().FullName);
Debug.Fail(msg);
}
}
#endregion // Private Helpers
#region Implementation of IEditableObject
public virtual void BeginEdit()
{
oldState = new HybridDictionary();
foreach (PropertyInfo property in this.GetType
().GetProperties())
{
if (property.CanWrite)
{
oldState[property.Name] = property.GetValue(this,
null);
}
}
}
public virtual void EndEdit()
{
oldState = null;
}
public virtual void CancelEdit()
{
foreach (PropertyInfo property in this.GetType
().GetProperties())
{
if (property.CanWrite)
{
property.SetValue(this, oldState[property.Name],
null);
}
}
oldState = null;
}
#endregion
#region Implementation of IDataErrorInfo
public abstract string this[string columnName] { get; }
public abstract string Error { get; }
#endregion
}
On Aug 24, 6:28 pm, José Romaniello <[email protected]> wrote:
> could your post the entity class?
>
> 2009/8/24 Chris Willard <[email protected]>
>
>
>
> > Hi José,
>
> > I am attempting to try out your ObservableSet implementation but am
> > having a couple of issues. First off I can't seem to get the global
> > registration working using the code you supplied below. I seems to be
> > ignoring the configuration property change and using the default
> > implementation. Below is how I am currently handling the
> > configuration.
>
> > private ISessionFactory BuildSessionFactory()
> > {
> > ISessionFactory result =
> > Fluently.Configure()
> > .Database(MsSqlConfiguration.MsSql2005
> > .ConnectionString(c => c
> > .FromConnectionStringWithKey
> > (ConnectionStringName))
> > .Cache(c => c
> > .UseQueryCache()
> > .ProviderClass<HashtableCacheProvider>
> > ())
> > .ShowSql())
> > .ExposeConfiguration(ConfigureLazyLoad)
> > .ExposeConfiguration(ConfigureCollectionType)
> > .Mappings(m => m
> > .FluentMappings.AddFromAssembly
> > (_MapAssembly)
>
> > .ConventionDiscovery.AddFromAssemblyOf<ClassConvention>
> > ())
> > .ExposeConfiguration(ConfigureValidator)
> > .BuildSessionFactory();
>
> > return result;
> > }
>
> > private void ConfigureCollectionType(Configuration
> > configuration)
> > {
> > configuration.SetProperty
> > (Cfg.Environment.CollectionTypeFactoryClass, typeof
>
> > (Collection.Observable.ObservableCollectionTypeFactory).AssemblyQualifiedName);
> > }
>
> > If I manually set the CollectionType within one of my mapping classes
> > (.CollectionType<ObservableSetType<SectionNumber>>();) it seems to
> > work, although I am getting an error (Collection Remove event must
> > specify item position) when I try to remove an item from the
> > collection.
>
> > Thanks again,
> > Chris
>
> > On Aug 24, 4:57 pm, José Romaniello <[email protected]> wrote:
> > > There is also an ObservableSet. I use this class as a "transient
> > observable
> > > set" since .net framework only have an observable list.
> > > In order to configure the collection type factory I use:
>
> > > configuration.Properties[Environment.CollectionTypeFactoryClass]
> > > = typeof (WpfCollectionTypeFactory).AssemblyQualifiedName;
>
> > > Stay in sync with the WPF sample (athttp://nhforge.org/blogs/nhibernate/
> > ).
>
> > > 2009/8/24 Chris Willard <[email protected]>
>
> > > > That is exactly what I needed! I really appreciate all your great
> > > > work...
>
> > > > Chris
>
> > > > On Aug 24, 3:02 pm, Fabio Maulo <[email protected]> wrote:
> > > > > The proposal of CollectionTypeFactoryClass is allow the substitutions
> > of
> > > > all
> > > > > persistent collections by default.If you want see an implementation
> > using
> > > > > observable collections it is available here:
> > > >http://code.google.com/p/unhaddins/source/browse/#svn/trunk/uNhAddIns.
> > ..
>
> > > > > <
> >http://code.google.com/p/unhaddins/source/browse/#svn/trunk/uNhAddIns..
> > > > .>You
> > > > > can change it according to the implementations you are using.
>
> > > > > 2009/8/24 Chris Willard <[email protected]>
>
> > > > > > Hello,
>
> > > > > > I am using the observable collections implementation from the
> > > > > > following post to handle collections within a WPF application.
>
> >http://happynomad121.blogspot.com/2007/12/collections-for-wpf-and-nhi.
> > > > ..
>
> > > > > > I am currently adding ".CollectionType<ObservableSetType<T>>()" to
> > > > > > each property within the fluent map classes but was wondering if
> > there
> > > > > > is a way to handle this type of thing globally. I have seen some
> > > > > > mention of setting the CollectionTypeFactoryClass but was not sure
> > how
> > > > > > (or if) that related to the actually collection implementation. I
> > am
> > > > > > sure I am just missing something simple. Any help would be greatly
> > > > > > appreciated!
>
> > > > > > Thanks in advance,
> > > > > > Chris
>
> > > > > --
> > > > > Fabio Maulo
>
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---