/// <summary> /// Binds the framework element to the given property. /// </summary> /// <param name="property">The data property to bind the framework element to.</param> public virtual void BindTo(DataProperty property) { if (this.property != null) this.property.Change -= OnPropertyChange; this.property = property; this.row = property != null ? property.Row : -1; if (property != null) { OnPropertyBound(); OnPropertyChange(property, new PropertyChangeEventArgs(PropertyChange.All, null, null)); // don't listen for data list properties, as it gets dispatched to the entire column // and significantly degrades performance if (property.Column < 0) property.Change += OnPropertyChange; } }
/// <summary> /// Binds the framework element to the given property. /// </summary> /// <param name="property">The data property to bind the framework element to.</param> /// <param name="row">The data row in a list to use as a context.</param> public virtual void BindTo(DataProperty property, DataRow row) { if (this.property != null) { this.property.Change -= OnPropertyChange; } this.property = property; this.row = row; if (property != null) { OnPropertyBound(); OnPropertyChange(property, new PropertyChangeEventArgs(PropertyChange.All, null, null, row)); // don't listen for data list properties, as it gets dispatched to the entire column // and significantly degrades performance if (!(property.GetParent() is DataListObject)) { property.Change += OnPropertyChange; } } }
/// <summary> /// Binds the framework element to the given property. /// </summary> /// <param name="property">The data property to bind the framework element to.</param> public virtual void BindTo(DataProperty property) { if (this.property != null) { this.property.Change -= OnPropertyChange; } this.property = property; this.row = property != null ? property.Row : -1; if (property != null) { OnPropertyBound(); OnPropertyChange(property, new PropertyChangeEventArgs(PropertyChange.All, null, null)); // don't listen for data list properties, as it gets dispatched to the entire column // and significantly degrades performance if (property.Column < 0) { property.Change += OnPropertyChange; } } }
/// <summary> /// A handler of the data context change that finds the data property in the context data object /// and binds the framework element to it. /// </summary> private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { DependencyObject element = sender as DependencyObject; if (element == null) { return; } DataObject obj = element.GetValue(FrameworkElement.DataContextProperty) as DataObject; string childPath = Property.GetChildObject(element); obj = FindChildObject(obj, childPath) as DataObject; string propertyName = Property.GetName(element); DataProperty dp = null; if (obj != null && propertyName != null) { dp = obj[propertyName]; } BindTo(dp); }
/// <summary> /// Sets the values of the given data row or, if the row is null, /// the data object from the given data contract object /// by copying the values of the data contract object fields to the /// data object properties or child objects with the same names. /// If there is no exact match between some data contract field names /// and the data object property names, this method can be overridden /// in the subclass to address each such case. /// </summary> /// <param name="dataContract">The data contract object to copy the values from.</param> /// <param name="options">Additional options for the operation.</param> /// <param name="row">The row to set the values for. /// <param name="token">Cancellation token.</param> /// Null to set values of the current data object.</param> protected async Task FromDataContractAsync(object dataContract, object options, DataRow row, CancellationToken token = default) { if (dataContract == null) { return; } SetModified(false, false); foreach (PropertyInfo pi in dataContract.GetType().GetProperties()) { object val = pi.GetValue(dataContract, null); DataProperty dp = this[pi.Name]; DataObject child; if (dp != null) { dp.Modified = null; await dp.SetValueAsync(val, row, token); } else if ((child = GetChildObject(pi.Name)) != null) { await child.FromDataContractAsync(val, options, token); } else if (val != null) { foreach (PropertyInfo cpi in pi.PropertyType.GetProperties()) { DataProperty cdp = this[pi.Name + "_" + cpi.Name]; if (cdp != null) { cdp.Modified = null; await cdp.SetValueAsync(cpi.GetValue(val, null), row, token); } } } } }
/// <summary> /// Exports the data object property values and child object values /// to the given data contract object by setting the specified properties /// of the data contract to the values of the corresponding properties /// or child objects with the same names. /// This method can be used to partially export data object values /// to a data contract object. /// </summary> /// <param name="dataContract">The data contract object to export /// the current data object values to.</param> /// <param name="props">The data contract object fields to set.</param> /// <param name="options">Additional options for the operation.</param> protected void ToDataContractProperties(object dataContract, PropertyInfo[] props, object options) { if (dataContract == null) { return; } foreach (PropertyInfo pi in props) { DataProperty dp = this[pi.Name]; if (dp != null) { if (dp.IsValid(true)) { if (dp.IsMultiValued) { IList lst = null; IEnumerable valLst = dp.TransportValue as IEnumerable; if (valLst != null) { // create the right type of list and copy the values rather than directly assign lst = CreateInstance(pi.PropertyType) as IList; if (lst != null) { foreach (object o in valLst) { lst.Add(o); } } } pi.SetValue(dataContract, lst, null); } else { pi.SetValue(dataContract, dp.TransportValue, null); } } continue; } object obj = null; try { obj = CreateInstance(pi.PropertyType); } catch { continue; } DataObject child = GetChildObject(pi.Name); if (child != null) { child.ToDataContract(obj, options); } else { foreach (PropertyInfo cpi in pi.PropertyType.GetProperties()) { DataProperty cdp = this[pi.Name + "_" + cpi.Name]; if (cdp != null && cdp.IsValid(true)) { cpi.SetValue(obj, cdp.TransportValue, null); } } } pi.SetValue(dataContract, obj, null); } }
/// <summary> /// Adds the specified property to the data object. /// </summary> /// <param name="property">The property to add to the data object.</param> internal void AddProperty(DataProperty property) { properties[property.Name] = property; }
/// <summary> /// Adds the specified property to the data object. /// </summary> /// <param name="property">The property to add to the data object.</param> internal void AddProperty(DataProperty property) { properties[property.Name] = property; property.Change += OnDataPropertyChange; }
/// <summary> /// Get space-delimited string with the property states using current descriptions. /// </summary> /// <param name="property">The data property to get the states for.</param> /// <param name="states">The combination of property states to return.</param> /// <param name="row">Specific data row for list objects, or null for regular data objects.</param> public virtual string GetStateDescription(DataProperty property, PropertyChange states, DataRow row) { var propertyStates = GetStates(property, states, row); return(string.Join(" ", propertyStates)); }
/// <summary> /// Returns a list of current field criteria settings. /// </summary> public List <FieldCriteriaSetting> GetFieldCriteriaSettings() { // get a map of properties Dictionary <string, DataProperty> map = new Dictionary <string, DataProperty>(); foreach (DataProperty p in Properties) { map.Add(p.Name, p); } // clear the map from properties that are associated with operators OperatorProperty op; foreach (DataProperty p in Properties) { if ((op = p as OperatorProperty) == null) { continue; } if (op.AdditionalPropertyName != null) { map.Remove(op.AdditionalPropertyName); } if (op.AdditionalPropertyName2 != null) { map.Remove(op.AdditionalPropertyName2); } } // export visible non-null settings List <FieldCriteriaSetting> res = new List <FieldCriteriaSetting>(); foreach (DataProperty p in map.Values) { if (p.IsNull() || !p.Visible) { continue; } if ((op = p as OperatorProperty) != null) { List <string> value = new List <string>(); foreach (var apn in new string[] { op.AdditionalPropertyName, op.AdditionalPropertyName2 }) { DataProperty v = apn != null ? this[apn] : null; if (v != null && !v.IsNull() && v.Visible) { value.Add(v.DisplayStringValue); } } res.Add(new FieldCriteriaSetting { Label = p.Label, Operator = op.DisplayStringValue, Value = value.ToArray() }); } else { res.Add(new FieldCriteriaSetting { Label = p.Label, Operator = null, Value = new string[] { p.DisplayStringValue } }); } } return(res); }
/// <summary> /// Binds the framework element to the given property. /// </summary> /// <param name="property">The data property to bind the framework element to.</param> public override void BindTo(DataProperty property) { base.BindTo(property); if (property == null) { element.SetValue(Property.ValidationProperty, null); BindingOperations.ClearBinding(element, ValidationExpressionProperty); } }
/// <summary> /// Copy value and state from another property (presumably of the same type). /// </summary> /// <param name="p">The property to copy the state from.</param> public virtual void CopyFrom(DataProperty p) { if (p == null) return; SetValue(p.InternalValue); Editable = p.Editable; Required = p.Required; AccessLevel = p.AccessLevel; Visible = p.Visible; }
/// <summary> /// A standard validation function that checks for null if the value is required. /// </summary> /// <param name="dp">Data property being validated.</param> /// <param name="value">The value to validate.</param> public static void ValidateRequired(DataProperty dp, object value) { if (dp != null && dp.Required && dp.IsValueNull(value, ValueFormat.Internal)) dp.ValidationErrors.AddError("{0} is required.", dp); }