Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / Windows / Data / DataSourceProvider.cs / 1305600 / DataSourceProvider.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: common base class and contract for data source provider objects // // Specs: http://avalon/connecteddata/Specs/Avalon%20DataProviders.mht // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.ComponentModel; using System.Threading; using System.Windows.Threading; // Dispatcher* using MS.Internal; // Invariant namespace System.Windows.Data { ////// Common base class and contract for data source providers. /// A DataProvider in Avalon is the factory that executes some query /// to produce a single object or a list of objects that can be used /// as sources for Avalon data bindings. /// It is a convenience wrapper around existing data model, it does not replace any data model. /// A data provider does not attempt to condense the complexity and versatility of a data model /// like ADO into one single object with a few properties. /// ////// DataSourceProvider is an abstract class and cannot directly be used as a data provider. /// Use one of the derived concrete provider, e.g. XmlDataProvider, ObjectDataProvider. /// The DataProvider aware of Avalon's threading and dispatcher model. The data provider assumes /// the thread at creation time to be the UI thread. Events will get marshalled from a worker thread /// to the app's UI thread. /// public abstract class DataSourceProvider : INotifyPropertyChanged, ISupportInitialize { ////// constructor captures the Dispatcher associated with the current thread /// protected DataSourceProvider() { _dispatcher = Dispatcher.CurrentDispatcher; } ////// Start the initial query to the underlying data model. /// The result will be returned on the Data property. /// This method is typically called by the binding engine when /// dependent data bindings are activated. /// Set IsInitialLoadEnabled = false to prevent or delay the automatic loading of data. /// ////// The InitialLoad method can be called multiple times. /// The provider is expected to ignore subsequent calls once the provider /// is busy executing the initial query, i.e. the provider shall not restart /// an already running query when InitialLoad is called again. /// When the query finishes successfully, any InitialLoad call will still not re-query data. /// The InitialLoad operation is typically asynchronous, a DataChanged event will /// be raised when the Data property assumed a new value. /// The application should call Refresh to cause a refresh of data. /// public void InitialLoad() { // ignore call if IsInitialLoadEnabled == false or already started initialization if (!IsInitialLoadEnabled || _initialLoadCalled) return; _initialLoadCalled = true; BeginQuery(); } ////// Initiates a Refresh Operation to the underlying data model. /// The result will be returned on the Data property. /// ////// A refresh operation is typically asynchronous, a DataChanged event will /// be raised when the Data property assumed a new value. /// If the refresh operation fails, the Data property will be set to null; /// the Error property will be set with the error exception. /// The app can call Refresh while a previous refresh is still underway. /// Calling Refresh twice will cause the DataChanged event to raise twice. /// public void Refresh() { _initialLoadCalled = true; BeginQuery(); } ////// Set IsInitialLoadEnabled = false to prevent or delay the automatic loading of data. /// [DefaultValue(true)] public bool IsInitialLoadEnabled { get { return _isInitialLoadEnabled; } set { _isInitialLoadEnabled = value; OnPropertyChanged(new PropertyChangedEventArgs("IsInitialLoadEnabled")); } } ////// Get the underlying data object. /// This is the resulting data source the data provider /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public object Data { get { return _data; } } ////// Raise this event when a new data object becomes available /// on the Data property. /// public event EventHandler DataChanged; ////// Return the error of the last query operation. /// To indicate there was no error, it will return null /// public Exception Error { get { return _error; } } ////// Enter a Defer Cycle. /// Defer cycles are used to coalesce property changes, any automatic /// Refresh is delayed until the Defer Cycle is exited. /// ////// most typical usage is with a using block to set multiple proporties /// without the automatic Refresh to occur /// public virtual IDisposable DeferRefresh() { ++_deferLevel; return new DeferHelper(this); } #region ISupportInitialize ////// XmlDataProvider xdv = new XmlDataProvider(); /// using(xdv.DeferRefresh()) { /// xdv.Source = "http://foo.com/bar.xml"; /// xdv.XPath = "/Bla/Baz[@Boo='xyz']"; /// } ///
////// Initialization of this element is about to begin /// void ISupportInitialize.BeginInit() { BeginInit(); } ////// Initialization of this element has completed /// void ISupportInitialize.EndInit() { EndInit(); } #endregion ////// PropertyChanged event (per event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { add { PropertyChanged += value; } remove { PropertyChanged -= value; } } //----------------------------------------------------- // // Protected Properties // //----------------------------------------------------- ///). /// /// IsRefreshDeferred returns true if there is still an /// outstanding DeferRefresh in use. To get the best use /// out of refresh deferral, derived classes should try /// not to call Refresh when IsRefreshDeferred is true. /// protected bool IsRefreshDeferred { get { return ( (_deferLevel > 0) || (!IsInitialLoadEnabled && !_initialLoadCalled)); } } ////// The current Dispatcher to the Avalon UI thread to use. /// ////// By default, this is the Dispatcher associated with the thread /// on which this DataProvider instance was created. /// protected Dispatcher Dispatcher { get { return _dispatcher; } set { if (_dispatcher != value) { _dispatcher = value; } } } //------------------------------------------------------ // // Protected Methods // //----------------------------------------------------- #region Protected Methods ////// Overridden by concrete data provider class. /// the base class will call this method when InitialLoad or Refresh /// has been called and will delay this call if refresh is deferred ot /// initial load is disabled. /// ////// The implementor can choose to execute the query on the same thread or /// on a background thread or using asynchronous API. /// When the query is complete, call OnQueryFinished to have the public properties updated. /// protected virtual void BeginQuery() { } ////// A concrete data provider will call this method /// to indicate that a query has finished. /// ////// This callback can be called from any thread, this implementation /// will marshal back the result to the UI thread /// before setting any of the public properties and before raising any events. /// resulting data from query /// protected void OnQueryFinished(object newData) { OnQueryFinished(newData, null, null, null); } ////// A concrete data provider will call this method /// to indicate that a query has finished. /// ////// This callback can be called from any thread, this implementation /// will marshal back the result to the UI thread /// before setting any of the public properties and before raising any events. /// resulting data from query /// error that occured while running query; null signals no error /// optional delegate to execute completion work on UI thread, e.g. setting additional properties /// optional arguments to send as parameter with the completionWork delegate /// protected virtual void OnQueryFinished(object newData, Exception error, DispatcherOperationCallback completionWork, object callbackArguments) { Invariant.Assert(Dispatcher != null); // check if we're already on the dispatcher thread if (Dispatcher.CheckAccess()) { // already on UI thread UpdateWithNewResult(error, newData, completionWork, callbackArguments); } else { // marshal the result back to the main thread Dispatcher.BeginInvoke( DispatcherPriority.Normal, UpdateWithNewResultCallback, new object[] { this, error, newData, completionWork, callbackArguments }); } } ////// PropertyChanged event (per protected virtual event PropertyChangedEventHandler PropertyChanged; ///). /// /// Raises a PropertyChanged event (per protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, e); } } ///). /// /// Initialization of this element is about to begin; /// no implicit Refresh occurs until the matched EndInit is called /// protected virtual void BeginInit() { ++_deferLevel; } ////// Initialization of this element has completed; /// this causes a Refresh if no other deferred refresh is outstanding /// protected virtual void EndInit() { EndDefer(); } #endregion Protected Methods //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private void EndDefer() { Debug.Assert(_deferLevel > 0); --_deferLevel; if (_deferLevel == 0) { Refresh(); } } private static object UpdateWithNewResult(object arg) { object[] args = (object[]) arg; Invariant.Assert(args.Length == 5); DataSourceProvider provider = (DataSourceProvider) args[0]; Exception error = (Exception) args[1]; object newData = args[2]; DispatcherOperationCallback completionWork = (DispatcherOperationCallback) args[3]; object callbackArgs = args[4]; provider.UpdateWithNewResult(error, newData, completionWork, callbackArgs); return null; } private void UpdateWithNewResult(Exception error, object newData, DispatcherOperationCallback completionWork, object callbackArgs) { bool errorChanged = (_error != error); _error = error; if (error != null) { newData = null; _initialLoadCalled = false; // allow again InitialLoad after an error } _data = newData; if (completionWork != null) completionWork(callbackArgs); // notify any listeners OnPropertyChanged(new PropertyChangedEventArgs("Data")); if (DataChanged != null) { DataChanged(this, EventArgs.Empty); } if (errorChanged) OnPropertyChanged(new PropertyChangedEventArgs("Error")); } #endregion Private Methods //----------------------------------------------------- // // Private Types // //------------------------------------------------------ #region Private Types private class DeferHelper : IDisposable { public DeferHelper(DataSourceProvider provider) { _provider = provider; } public void Dispose() { GC.SuppressFinalize(this); if (_provider != null) { _provider.EndDefer(); _provider = null; } } private DataSourceProvider _provider; } #endregion //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- private bool _isInitialLoadEnabled = true; private bool _initialLoadCalled; private int _deferLevel; private object _data; private Exception _error; private Dispatcher _dispatcher; static readonly DispatcherOperationCallback UpdateWithNewResultCallback = new DispatcherOperationCallback(UpdateWithNewResult); } } // 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
- SimpleMailWebEventProvider.cs
- ReverseInheritProperty.cs
- ScrollChrome.cs
- ScriptingAuthenticationServiceSection.cs
- Match.cs
- ColumnCollection.cs
- RemoteWebConfigurationHost.cs
- StrokeCollectionDefaultValueFactory.cs
- SubstitutionList.cs
- SoapServerMethod.cs
- WebPartDescriptionCollection.cs
- SqlCaseSimplifier.cs
- TextBox.cs
- RawAppCommandInputReport.cs
- MD5CryptoServiceProvider.cs
- ObjectDataSourceFilteringEventArgs.cs
- DocumentXmlWriter.cs
- AssertFilter.cs
- CaseExpr.cs
- DoubleLinkListEnumerator.cs
- SymbolMethod.cs
- clipboard.cs
- DocumentAutomationPeer.cs
- SourceLineInfo.cs
- ImageCodecInfoPrivate.cs
- ValidationResult.cs
- OracleInfoMessageEventArgs.cs
- ControlValuePropertyAttribute.cs
- FilterQueryOptionExpression.cs
- WindowsNonControl.cs
- LineServices.cs
- WebAdminConfigurationHelper.cs
- FlowStep.cs
- _FtpDataStream.cs
- ValueUtilsSmi.cs
- MatrixAnimationBase.cs
- EdmComplexTypeAttribute.cs
- IdentityHolder.cs
- FormViewModeEventArgs.cs
- BinaryNode.cs
- Triplet.cs
- UnsafeNativeMethods.cs
- QilNode.cs
- WebResourceUtil.cs
- HttpWriter.cs
- MouseGestureConverter.cs
- ClientCredentialsSecurityTokenManager.cs
- DependencyProperty.cs
- EqualityComparer.cs
- ColorBlend.cs
- BigInt.cs
- HttpAsyncResult.cs
- ObfuscateAssemblyAttribute.cs
- HeaderedContentControl.cs
- XmlSchema.cs
- _AuthenticationState.cs
- MulticastDelegate.cs
- CodeAssignStatement.cs
- BooleanConverter.cs
- SmtpNetworkElement.cs
- CqlQuery.cs
- SiteMapNodeItemEventArgs.cs
- ListControlDesigner.cs
- EngineSite.cs
- Control.cs
- StylusPointPropertyInfoDefaults.cs
- Dispatcher.cs
- WindowsComboBox.cs
- Primitive.cs
- HttpResponseInternalWrapper.cs
- ImageSourceValueSerializer.cs
- ByteStream.cs
- PolicyChain.cs
- XamlContextStack.cs
- cache.cs
- GenerateTemporaryTargetAssembly.cs
- x509utils.cs
- TimeSpanOrInfiniteConverter.cs
- InplaceBitmapMetadataWriter.cs
- GridToolTip.cs
- DispatcherTimer.cs
- FileAuthorizationModule.cs
- DataGridViewCellStyleConverter.cs
- AnyReturnReader.cs
- XmlSchemaObjectCollection.cs
- GeneralTransform2DTo3D.cs
- DesignerContextDescriptor.cs
- SubMenuStyle.cs
- SurrogateEncoder.cs
- ContextQuery.cs
- ContractsBCL.cs
- StringExpressionSet.cs
- UrlMapping.cs
- ColumnMapVisitor.cs
- MasterPageParser.cs
- _ConnectOverlappedAsyncResult.cs
- wgx_render.cs
- WindowsEditBoxRange.cs
- TextRangeEditTables.cs
- AnnotationDocumentPaginator.cs