Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Data / CLRBindingWorker.cs / 1305600 / CLRBindingWorker.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: Defines ClrBindingWorker object, workhorse for CLR bindings // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Reflection; using System.Globalization; using System.Windows.Threading; using System.Threading; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Controls; // Validation using System.Windows.Data; using System.Windows.Markup; // for GetTypeFromName using MS.Internal.Controls; // Validation using MS.Internal.Utility; // for GetTypeFromName using MS.Utility; namespace MS.Internal.Data { internal class ClrBindingWorker : BindingWorker { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- internal ClrBindingWorker(BindingExpression b, DataBindEngine engine) : base(b) { PropertyPath path = ParentBinding.Path; if (ParentBinding.XPath != null) { path = PrepareXmlBinding(path); } if (path == null) { path = new PropertyPath(String.Empty); } if (ParentBinding.Path == null) { ParentBinding.UsePath(path); } _pathWorker = new PropertyPathWorker(path, this, IsDynamic, engine); _pathWorker.SetTreeContext(ParentBindingExpression.TargetElementReference); } // separate method to avoid loading System.Xml if not needed [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] PropertyPath PrepareXmlBinding(PropertyPath path) { if (path == null) { DependencyProperty targetDP = TargetProperty; Type targetType = targetDP.PropertyType; string pathString; if (targetType == typeof(Object)) { if (targetDP == System.Windows.Data.BindingExpression.NoTargetProperty || targetDP == System.Windows.Controls.Primitives.Selector.SelectedValueProperty) { // these properties want the "value" - i.e. the text of // the first (and usually only) XmlNode pathString = "/InnerText"; } else if (targetDP == FrameworkElement.DataContextProperty || targetDP == CollectionViewSource.SourceProperty) { // these properties want the entire collection pathString = String.Empty; } else { // most object-valued properties want the (current) XmlNode itself pathString = "/"; } } else if (targetType.IsAssignableFrom(typeof(XmlDataCollection))) { // these properties want the entire collection pathString = String.Empty; } else { // most other properties want the "value" pathString = "/InnerText"; } path = new PropertyPath(pathString); } // don't bother to create XmlWorker if we don't even have a valid path if (path.SVI.Length > 0) { // tell Xml Worker if desired result is collection, in order to get optimization _xmlWorker = new XmlBindingWorker(this, path.SVI[0].drillIn == DrillIn.Never); } return path; } //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- internal override Type SourcePropertyType { get { return PW.GetType(PW.Length - 1); } } internal override bool IsDBNullValidForUpdate { get { return PW.IsDBNullValidForUpdate; } } internal override object SourceItem { get { return PW.SourceItem; } } internal override string SourcePropertyName { get { return PW.SourcePropertyName; } } //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ internal override bool CanUpdate { get { PropertyPathWorker ppw = PW; int k = PW.Length - 1; if (k < 0) return false; object item = ppw.GetItem(k); if (item == null || item == BindingExpression.NullDataItem) return false; object accessor = ppw.GetAccessor(k); if (accessor == null || (accessor == DependencyProperty.UnsetValue && XmlWorker == null)) return false; return true; } } internal override void AttachDataItem() { object item; if (XmlWorker == null) { item = DataItem; } else { XmlWorker.AttachDataItem(); item = XmlWorker.RawValue(); } PW.AttachToRootItem(item); if (PW.Length == 0) { ParentBindingExpression.SetupDefaultValueConverter(item.GetType()); } } internal override void DetachDataItem() { PW.DetachFromRootItem(); if (XmlWorker != null) { XmlWorker.DetachDataItem(); } // cancel any pending async requests. If it has already completed, // but is now waiting in the dispatcher queue, it will be ignored because // we set _pending*Request to null. if (_pendingGetValueRequest != null) { _pendingGetValueRequest.Cancel(); _pendingGetValueRequest = null; } if (_pendingSetValueRequest != null) { _pendingSetValueRequest.Cancel(); _pendingSetValueRequest = null; } } internal override object RawValue() { object rawValue = PW.RawValue(); SetStatus(PW.Status); return rawValue; } internal override void RefreshValue() { PW.RefreshValue(); } internal override void UpdateValue(object value) { int k = PW.Length - 1; object item = PW.GetItem(k); if (item == null || item == BindingExpression.NullDataItem) return; // if the binding is async, post a request to set the value if (ParentBinding.IsAsync && !(PW.GetAccessor(k) is DependencyProperty)) { RequestAsyncSetValue(item, value); return; } PW.SetValue(item, value); } internal override void OnCurrentChanged(ICollectionView collectionView, EventArgs args) { if (XmlWorker != null) XmlWorker.OnCurrentChanged(collectionView, args); PW.OnCurrentChanged(collectionView); } internal override bool UsesDependencyProperty(DependencyObject d, DependencyProperty dp) { return PW.UsesDependencyProperty(d, dp); } internal override void OnSourceInvalidation(DependencyObject d, DependencyProperty dp, bool isASubPropertyChange) { PW.OnDependencyPropertyChanged(d, dp, isASubPropertyChange); } internal override ValidationError ValidateDataError(BindingExpressionBase bindingExpressionBase) { return PW.ValidateDataError(bindingExpressionBase); } internal override bool IsPathCurrent() { object item = (XmlWorker == null) ? DataItem : XmlWorker.RawValue(); return PW.IsPathCurrent(item); } //----------------------------------------------------- // // Internal Properties - callbacks from PropertyPathWorker // //------------------------------------------------------ internal bool TransfersDefaultValue { get { return ParentBinding.TransfersDefaultValue; } } //----------------------------------------------------- // // Internal Methods - callbacks from PropertyPathWorker // //----------------------------------------------------- internal void CancelPendingTasks() { ParentBindingExpression.CancelPendingTasks(); } internal bool AsyncGet(object item, int level) { if (ParentBinding.IsAsync) { RequestAsyncGetValue(item, level); return true; } else return false; } internal void ReplaceCurrentItem(ICollectionView oldCollectionView, ICollectionView newCollectionView) { // detach from old view if (oldCollectionView != null) { CurrentChangedEventManager.RemoveListener(oldCollectionView, ParentBindingExpression); if (IsReflective) { CurrentChangingEventManager.RemoveListener(oldCollectionView, ParentBindingExpression); } } // attach to new view if (newCollectionView != null) { CurrentChangedEventManager.AddListener(newCollectionView, ParentBindingExpression); if (IsReflective) { CurrentChangingEventManager.AddListener(newCollectionView, ParentBindingExpression); } } } internal void NewValueAvailable(bool dependencySourcesChanged, bool initialValue, bool isASubPropertyChange) { SetStatus(PW.Status); BindingExpression parent = ParentBindingExpression; // this method is called when the last item in the path is replaced. // BindingGroup also wants to know about this. BindingGroup bindingGroup = parent.BindingGroup; if (bindingGroup != null) { bindingGroup.UpdateTable(parent); } if (dependencySourcesChanged) { ReplaceDependencySources(); } // if there's a revised value (i.e. not during initialization // and shutdown), transfer it. if (!initialValue && Status != BindingStatus.AsyncRequestPending) { parent.ScheduleTransfer(isASubPropertyChange); } } internal void SetupDefaultValueConverter(Type type) { ParentBindingExpression.SetupDefaultValueConverter(type); } internal bool IsValidValue(object value) { return TargetProperty.IsValidValue(value); } internal void OnSourcePropertyChanged(object o, string propName) { int level; // ignore changes that don't affect this binding. // This test must come before any marshalling to the right context (bug 892484) if (!IgnoreSourcePropertyChange && (level = PW.LevelForPropertyChange(o, propName)) >= 0) { // if notification was on the right thread, just do the work (normal case) if (Dispatcher.Thread == Thread.CurrentThread) { PW.OnPropertyChangedAtLevel(level); } else { // otherwise invoke an operation to do the work on the right context SetTransferIsPending(true); Dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback(ScheduleTransferOperation), new object[]{o, propName}); } } } // called by the child XmlBindingWorker when an xml change is detected // but the identity of raw value has not changed. internal void OnXmlValueChanged() { // treat this as a property change at the top level object item = PW.GetItem(0); OnSourcePropertyChanged(item, null); } // called by the child XmlBindingWorker when there's a new raw value internal void UseNewXmlItem(object item) { PW.DetachFromRootItem(); PW.AttachToRootItem(item); if (Status != BindingStatus.AsyncRequestPending) { ParentBindingExpression.ScheduleTransfer(false); } } // called by the child XmlBindingWorker to get the current "result node" internal object GetResultNode() { return PW.GetItem(0); } internal DependencyObject CheckTarget() { // if the target has been GC'd, this will shut down the binding return TargetElement; } internal void ReportGetValueError(int k, object item, Exception ex) { if (TraceData.IsEnabled) { SourceValueInfo svi = PW.GetSourceValueInfo(k); Type type = PW.GetType(k); string parentName = (k>0)? PW.GetSourceValueInfo(k-1).name : String.Empty; TraceData.Trace(ParentBindingExpression.TraceLevel, TraceData.CannotGetClrRawValue( svi.propertyName, type.Name, parentName, AvTrace.TypeName(item)), ParentBindingExpression, ex); } } internal void ReportSetValueError(int k, object item, object value, Exception ex) { if (TraceData.IsEnabled) { SourceValueInfo svi = PW.GetSourceValueInfo(k); Type type = PW.GetType(k); TraceData.Trace(TraceEventType.Error, TraceData.CannotSetClrRawValue( svi.propertyName, type.Name, AvTrace.TypeName(item), AvTrace.ToStringHelper(value), AvTrace.TypeName(value)), ParentBindingExpression, ex); } } internal void ReportRawValueErrors(int k, object item, object info) { if (TraceData.IsEnabled) { if (item == null) { // There is probably no data item; e.g. we've moved currency off of a list. // the type of the missing item is supposed to be _arySVS[k].info.DeclaringType // the property we're looking for is named _arySVS[k].name TraceData.Trace(TraceEventType.Information, TraceData.MissingDataItem, ParentBindingExpression); } if (info == null) { // this no info problem should have been error reported at ReplaceItem already. // this can happen when parent is Nullable with no value // check _arySVS[k-1].info.ComponentType //if (!IsNullableType(_arySVS[k-1].info.ComponentType)) TraceData.Trace(TraceEventType.Information, TraceData.MissingInfo, ParentBindingExpression); } if (item == BindingExpression.NullDataItem) { // this is OK, not an error. // this can happen when detaching bindings. // this can happen when binding has a Nullable data item with no value TraceData.Trace(TraceEventType.Information, TraceData.NullDataItem, ParentBindingExpression); } } } internal void ReportBadXPath(TraceEventType traceType) { if (_xmlWorker != null) { _xmlWorker.ReportBadXPath(traceType); } } //----------------------------------------------------- // // Private Properties // //------------------------------------------------------ PropertyPathWorker PW { get { return _pathWorker; } } XmlBindingWorker XmlWorker { get { return _xmlWorker; } } //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ void SetStatus(PropertyPathStatus status) { switch (status) { case PropertyPathStatus.Inactive: Status = BindingStatus.Inactive; break; case PropertyPathStatus.Active: Status = BindingStatus.Active; break; case PropertyPathStatus.PathError: Status = BindingStatus.PathError; break; case PropertyPathStatus.AsyncRequestPending: Status = BindingStatus.AsyncRequestPending; break; } } void ReplaceDependencySources() { if (!ParentBindingExpression.IsDetaching) { int size = PW.Length; if (PW.NeedsDirectNotification) ++size; WeakDependencySource[] newSources = new WeakDependencySource[size]; int n = 0; if (IsDynamic) { for (int k=0; k= 0) { PW.OnPropertyChangedAtLevel(level); } return null; } #endregion Callbacks //------------------------------------------------------ // // Private Enums, Structs, Constants // //----------------------------------------------------- static readonly AsyncRequestCallback DoGetValueCallback = new AsyncRequestCallback(OnGetValueCallback); static readonly AsyncRequestCallback CompleteGetValueCallback = new AsyncRequestCallback(OnCompleteGetValueCallback); static readonly DispatcherOperationCallback CompleteGetValueLocalCallback = new DispatcherOperationCallback(OnCompleteGetValueOperation); static readonly AsyncRequestCallback DoSetValueCallback = new AsyncRequestCallback(OnSetValueCallback); static readonly AsyncRequestCallback CompleteSetValueCallback = new AsyncRequestCallback(OnCompleteSetValueCallback); static readonly DispatcherOperationCallback CompleteSetValueLocalCallback = new DispatcherOperationCallback(OnCompleteSetValueOperation); //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- PropertyPathWorker _pathWorker; XmlBindingWorker _xmlWorker; AsyncGetValueRequest _pendingGetValueRequest; AsyncSetValueRequest _pendingSetValueRequest; Type[] _types = new Type[1]; object[] _values = new object[1]; } internal class WeakDependencySource { internal WeakDependencySource(DependencyObject item, DependencyProperty dp) { _item = BindingExpressionBase.CreateReference(item); _dp = dp; } internal WeakDependencySource(WeakReference wr, DependencyProperty dp) { _item = wr; _dp = dp; } internal DependencyObject DependencyObject { get { return (DependencyObject)BindingExpressionBase.GetReference(_item); } } internal DependencyProperty DependencyProperty { get { return _dp; } } object _item; DependencyProperty _dp; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BindingNavigator.cs
- SqlFlattener.cs
- LinqDataSourceView.cs
- GridViewCommandEventArgs.cs
- DateTimeUtil.cs
- ConversionValidationRule.cs
- AuthenticationException.cs
- RawMouseInputReport.cs
- AbandonedMutexException.cs
- InstanceData.cs
- NegatedConstant.cs
- RoleServiceManager.cs
- DesignColumnCollection.cs
- SerialPinChanges.cs
- SiteMapNodeItemEventArgs.cs
- ConstraintEnumerator.cs
- ClientConfigPaths.cs
- IsolatedStoragePermission.cs
- FilterableAttribute.cs
- Selection.cs
- RightNameExpirationInfoPair.cs
- InputScope.cs
- LinearGradientBrush.cs
- PrePostDescendentsWalker.cs
- EventMappingSettings.cs
- OutputScope.cs
- XmlSiteMapProvider.cs
- Point3DKeyFrameCollection.cs
- MediaElementAutomationPeer.cs
- FloaterParagraph.cs
- SelectedGridItemChangedEvent.cs
- MapPathBasedVirtualPathProvider.cs
- RotateTransform3D.cs
- Drawing.cs
- DecimalFormatter.cs
- ViewKeyConstraint.cs
- WinFormsUtils.cs
- DependencyPropertyChangedEventArgs.cs
- Touch.cs
- CodeTypeParameter.cs
- ClientSideProviderDescription.cs
- EditorPartChrome.cs
- TableLayoutPanelCellPosition.cs
- DataGridViewCellPaintingEventArgs.cs
- QilFactory.cs
- ColorConvertedBitmap.cs
- ValidationRule.cs
- BufferedWebEventProvider.cs
- IconBitmapDecoder.cs
- ResolveDuplexCD1AsyncResult.cs
- UriSchemeKeyedCollection.cs
- InternalBase.cs
- AlphabetConverter.cs
- DataKey.cs
- FixedSOMImage.cs
- HybridWebProxyFinder.cs
- GACMembershipCondition.cs
- CompiledIdentityConstraint.cs
- ParameterCollectionEditorForm.cs
- QueryLifecycle.cs
- ToolStripItemTextRenderEventArgs.cs
- CodeGroup.cs
- FontSizeConverter.cs
- UdpChannelListener.cs
- PageTheme.cs
- CursorEditor.cs
- BitmapEffectInputConnector.cs
- MaskInputRejectedEventArgs.cs
- SmtpNetworkElement.cs
- SourceFileInfo.cs
- DeviceSpecific.cs
- MulticastDelegate.cs
- XmlObjectSerializerReadContextComplexJson.cs
- CategoryList.cs
- NegotiationTokenProvider.cs
- AuthenticationException.cs
- ConfigurationSettings.cs
- DbSource.cs
- ListManagerBindingsCollection.cs
- DoubleAverageAggregationOperator.cs
- SeparatorAutomationPeer.cs
- Pointer.cs
- XPathNodeIterator.cs
- ProfileProvider.cs
- DataListItem.cs
- SamlAuthorizationDecisionStatement.cs
- UriSection.cs
- DataException.cs
- XsltLoader.cs
- NewArray.cs
- DecoderFallback.cs
- DataChangedEventManager.cs
- TextModifier.cs
- VideoDrawing.cs
- X509Chain.cs
- XPathPatternParser.cs
- CodeLinePragma.cs
- ObjectParameterCollection.cs
- ConfigurationErrorsException.cs
- BlurBitmapEffect.cs