using System; using System.ComponentModel; using System.Collections.Generic; using System.Windows.Forms; using System.Reflection; namespace Csla.Windows { /// /// Windows Forms extender control that automatically /// enables and disables detail form controls based /// on the authorization settings from a CSLA .NET /// business object. /// [DesignerCategory("")] [ProvideProperty("ApplyAuthorization", typeof(Control))] public class ReadWriteAuthorization : Component, IExtenderProvider { private Dictionary _sources = new Dictionary(); /// /// Creates an instance of the object. /// /// The container of the control. public ReadWriteAuthorization(IContainer container) { container.Add(this); } /// /// Gets a value indicating whether the extender control /// can extend the specified control. /// /// The control to be extended. /// /// Any control implementing either a ReadOnly property or /// Enabled property can be extended. /// public bool CanExtend(object extendee) { if (IsPropertyImplemented(extendee, "ReadOnly") || IsPropertyImplemented(extendee, "Enabled")) return true; else return false; } /// /// Gets the custom ApplyAuthorization extender /// property added to extended controls. /// /// Control being extended. public bool GetApplyAuthorization(Control source) { if (_sources.ContainsKey(source)) return _sources[source]; else return false; } /// /// Sets the custom ApplyAuthorization extender /// property added to extended controls. /// /// Control being extended. /// New value of property. public void SetApplyAuthorization(Control source, bool value) { if (_sources.ContainsKey(source)) _sources[source] = value; else _sources.Add(source, value); } /// /// Causes the ReadWriteAuthorization control /// to apply authorization rules from the business /// object to all extended controls on the form. /// /// /// Call this method to refresh the display of detail /// controls on the form any time the authorization /// rules may have changed. Examples include: after /// a user logs in or out, and after an object has /// been updated, inserted, deleted or retrieved /// from the database. /// public void ResetControlAuthorization() { foreach (KeyValuePair item in _sources) { if (item.Value) { // apply authorization rules ApplyAuthorizationRules(item.Key); } } } private void ApplyAuthorizationRules(Control control) { foreach (Binding binding in control.DataBindings) { // get the BindingSource if appropriate if (binding.DataSource is BindingSource) { BindingSource bs = (BindingSource)binding.DataSource; // get the BusinessObject if appropriate Csla.Security.IAuthorizeReadWrite ds = bs.Current as Csla.Security.IAuthorizeReadWrite; if (ds != null) { // get the object property name string propertyName = binding.BindingMemberInfo.BindingField; ApplyReadRules( control, binding, ds.CanReadProperty(propertyName)); ApplyWriteRules( control, binding, ds.CanWriteProperty(propertyName)); } } } } private void ApplyReadRules( Control ctl, Binding binding, bool canRead) { // enable/disable reading of the value if (canRead) { bool couldRead = ctl.Enabled; ctl.Enabled = true; binding.Format -= new ConvertEventHandler(ReturnEmpty); if (!couldRead) binding.ReadValue(); } else { ctl.Enabled = false; binding.Format += new ConvertEventHandler(ReturnEmpty); // clear the value displayed by the control PropertyInfo propertyInfo = ctl.GetType().GetProperty(binding.PropertyName, BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public); if (propertyInfo != null) { propertyInfo.SetValue(ctl, GetEmptyValue( Utilities.GetPropertyType( propertyInfo.PropertyType)), new object[] { }); } } } private void ApplyWriteRules( Control ctl, Binding binding, bool canWrite) { if (ctl is Label) return; // enable/disable writing of the value PropertyInfo propertyInfo = ctl.GetType().GetProperty("ReadOnly", BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public); if (propertyInfo != null) { bool couldWrite = (!(bool)propertyInfo.GetValue( ctl, new object[] { })); propertyInfo.SetValue( ctl, !canWrite, new object[] { }); if ((!couldWrite) && (canWrite)) binding.ReadValue(); } else { bool couldWrite = ctl.Enabled; ctl.Enabled = canWrite; if ((!couldWrite) && (canWrite)) binding.ReadValue(); } } private void ReturnEmpty( object sender, ConvertEventArgs e) { e.Value = GetEmptyValue(e.DesiredType); } private object GetEmptyValue(Type desiredType) { object result = null; if (desiredType.IsValueType) result = Activator.CreateInstance(desiredType); return result; } private static bool IsPropertyImplemented( object obj, string propertyName) { if (obj.GetType().GetProperty(propertyName, BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public) != null) return true; else return false; } } }