The use is very simple:
Code: Select all
class MyModel inherit ExpandoBase
constructor()
self:SetValue( "Caption", "window caption" )
return
And this is the class:
Code: Select all
using System
using System.Collections.Generic
using System.Text
using System.Threading.Tasks
using System.ComponentModel
using System.Diagnostics
using System.Runtime.CompilerServices
using System.Dynamic
begin namespace rdm.MVVMHelper
/// <summary>
/// Baseclass for a dynamic object, implementing the INotifyPropertyChanged interface.
/// Here'a sample for using the "normal" properties:
/// public string FirstName
/// {
/// get { return _Get<string>(); }
/// set { _Set<string>(value); }
/// }
/// </summary>
public abstract class ExpandoBase inherit DynamicObject implements INotifyPropertyChanged
protect _oProperties := Dictionary<string, object>{} as Dictionary<string, object>
public event PropertyChanged as PropertyChangedEventHandler
/// <summary>
/// When a new property is set,
/// add the property name and value to the dictionary
/// </summary>
public virtual method TrySetMember( oBinder as SetMemberBinder, value as object ) as logic
if ! _oProperties.ContainsKey( oBinder.Name )
_oProperties.Add( oBinder.Name, value )
else
_oProperties[oBinder.Name] := value
endif
self:OnPropertyChanged( oBinder.Name )
return true
/// <summary>
/// When user accesses something, return the value if we have it
/// </summary>
public virtual method TryGetMember( oBinder as GetMemberBinder, result out object ) as logic
local lReturnValue as logic
if _oProperties.ContainsKey( oBinder:Name )
result := _oProperties[oBinder:Name]
lReturnValue := true
else
lReturnValue := super:TryGetMember( oBinder, out result )
endif
return lReturnValue
/// <summary>
/// If a property value is a delegate, invoke it
/// </summary>
public virtual method TryInvokeMember( oBinder as InvokeMemberBinder, args as object[], result out object ) as logic
local lReturnValue as logic
if _oProperties.ContainsKey( oBinder:Name ) .and. _oProperties[oBinder:Name] is System.Delegate
result := ( ( System.delegate ) _oProperties[oBinder:Name] ):DynamicInvoke( args )
lReturnValue := true
else
lReturnValue := super:TryInvokeMember( oBinder, args, out result )
endif
return lReturnValue
/// <summary>
/// Gets the value of a dynamic property
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <returns></returns>
public method GetValue( cName as string ) as object
local oValue as object
Debug.Assert( cName != null, "cName == null")
oValue := null
_oProperties.TryGetValue( cName, out oValue )
return oValue
/// <summary>
/// Sets the value of a dynamic property
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="name"></param>
/// <remarks>Use this overload when implicitly naming the property</remarks>
public method SetValue( cName as string, oValue as object ) as void
Debug.Assert( cName != null, "cName == null")
if Equals( oValue, GetValue( cName ) )
return
endif
_oProperties[cName] := oValue
OnPropertyChanged( cName )
return
/// <summary>
/// Gets the value of a property
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <returns></returns>
protected method _Get<T>( [CallerMemberName] cName := null as string ) as T
local value := null as object
Debug.Assert( cName != null, "cName != null" )
if _oProperties.TryGetValue( cName, out value )
if value == null
return Default(T)
else
return (T) value
endif
// return value == null ? Default(T) : (T)value
endif
return Default(T)
/// <summary>
/// Sets the value of a property
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="name"></param>
/// <remarks>Use this overload when implicitly naming the property</remarks>
protected method _Set<T>( value as T, [CallerMemberName] cName := null as string ) as void
Debug.Print( "passed Name is " + cName + ", passed value is " + value.ToString() )
Debug.Assert( cName != null, "cName != null" )
if ( Equals( value, _Get<T>( cName) ) )
return
endif
_oProperties[cName] := value
OnPropertyChanged( cName )
return
/// <summary>
/// Return all dynamic member names
/// </summary>
/// <returns>
public virtual method GetDynamicMemberNames() as IEnumerable<string>
return _oProperties.Keys
protected virtual method OnPropertyChanged([CallerMemberName] cPropertyName := null as string ) as void
local handler as PropertyChangedEventHandler
handler := self:PropertyChanged
if handler != null
handler( self, PropertyChangedEventArgs{ cPropertyName } )
endif
return
end class
end namespace