Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Input / InputLanguageManager.cs / 1 / InputLanguageManager.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: InputLanguageManager class and InputLanguage APIs. // // History: // 07/30/2003 : yutakas - ported from dotnet tree. // //--------------------------------------------------------------------------- using System.Collections; using System.Windows.Threading; using System.Windows; using System.Globalization; using MS.Win32; using System; using System.Security; using System.Runtime.InteropServices; using System.ComponentModel; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Input { ////// The InputLanguageManager class is responsible for mmanaging /// the input language in Avalon. /// public sealed class InputLanguageManager : DispatcherObject { ////// This is the property of the preferred input language of the /// element. /// When the element get focus, this input language is selected /// automatically. /// public static readonly DependencyProperty InputLanguageProperty = DependencyProperty.RegisterAttached( "InputLanguage", typeof(CultureInfo), typeof(InputLanguageManager), new PropertyMetadata(CultureInfo.InvariantCulture) ); ////// Setter for InputLanguage DependencyProperty /// public static void SetInputLanguage(DependencyObject target, CultureInfo inputLanguage) { if (target == null) { throw new ArgumentNullException("target"); } target.SetValue(InputLanguageProperty, inputLanguage); } ////// Getter for InputLanguage DependencyProperty /// [AttachedPropertyBrowsableForType(typeof(DependencyObject))] [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))] public static CultureInfo GetInputLanguage(DependencyObject target) { if (target == null) { throw new ArgumentNullException("target"); } return (CultureInfo)(target.GetValue(InputLanguageProperty)); } ////// If this is true, the previous inputlanguage is restored /// when the element with InputLanguage dynamicproperty lose the focus. /// This property is ignored if InputLanguage dynamic property is /// not available in the element. /// public static readonly DependencyProperty RestoreInputLanguageProperty = DependencyProperty.RegisterAttached( "RestoreInputLanguage", typeof(bool), typeof(InputLanguageManager), new PropertyMetadata(false) ); ////// Setter for RestoreInputLanguage DependencyProperty /// public static void SetRestoreInputLanguage(DependencyObject target, bool restore) { if (target == null) { throw new ArgumentNullException("target"); } target.SetValue(RestoreInputLanguageProperty, restore); } ////// Getter for RestoreInputLanguage DependencyProperty /// [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static bool GetRestoreInputLanguage(DependencyObject target) { if (target == null) { throw new ArgumentNullException("target"); } return (bool)(target.GetValue(RestoreInputLanguageProperty)); } //----------------------------------------------------- // // Constructors // //----------------------------------------------------- private InputLanguageManager() { // register our default input language source. RegisterInputLanguageSource(new InputLanguageSource(this)); } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods ////// Registers an input language soruces with the input /// input language manager. /// /// /// The input language source to register. /// public void RegisterInputLanguageSource(IInputLanguageSource inputLanguageSource) { if (inputLanguageSource == null) { throw new ArgumentNullException("inputLanguageSource"); } _source = inputLanguageSource; if (((_InputLanguageChanged != null) || (_InputLanguageChanging != null)) && IsMultipleKeyboardLayout) _source.Initialize(); return; } ////// Report the input language is changed from the source. /// /// /// The new language id. /// /// /// The previous language id. /// public void ReportInputLanguageChanged( CultureInfo newLanguageId, CultureInfo previousLanguageId) { if (newLanguageId == null) { throw new ArgumentNullException("newLanguageId"); } if (previousLanguageId == null) { throw new ArgumentNullException("previousLanguageId"); } // // if this language change was not done by SetFocus() and // InputLanguage Property of the element, we clear _previousLanguageId. // if (!previousLanguageId.Equals(_previousLanguageId)) { _previousLanguageId = null; } if (_InputLanguageChanged != null) { InputLanguageChangedEventArgs args = new InputLanguageChangedEventArgs(newLanguageId, previousLanguageId); // Stability Review: Task#32416 // - No state to be restored even exception happens while this callback. _InputLanguageChanged(this, args); } } ////// Report the input language is being changed from the source. /// /// /// The new language id. /// /// /// The previous language id. /// public bool ReportInputLanguageChanging( CultureInfo newLanguageId, CultureInfo previousLanguageId) { if (newLanguageId == null) { throw new ArgumentNullException("newLanguageId"); } if (previousLanguageId == null) { throw new ArgumentNullException("previousLanguageId"); } bool accepted = true; if (_InputLanguageChanging != null) { InputLanguageChangingEventArgs args = new InputLanguageChangingEventArgs(newLanguageId, previousLanguageId); // Stability Review: Task#32416 // - No state to be restored even exception happens while this callback. _InputLanguageChanging(this, args); accepted = args.Rejected ? false : true; } return accepted; } #endregion Public Methods //------------------------------------------------------ // // Public Operators // //------------------------------------------------------ //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ ////// Return the input language manager associated /// with the current context. /// public static InputLanguageManager Current { get { // InputLanguageManager for the current Dispatcher is stored in InputMethod of // the current Dispatcher. if(InputMethod.Current.InputLanguageManager == null) { InputMethod.Current.InputLanguageManager = new InputLanguageManager(); } return InputMethod.Current.InputLanguageManager; } } ////// This accesses the input language associated /// with the current context. /// [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))] public CultureInfo CurrentInputLanguage { get { // If the source is available, we should use it. if (_source != null) { return _source.CurrentInputLanguage; } IntPtr hkl = SafeNativeMethods.GetKeyboardLayout(0); if (hkl == IntPtr.Zero) { return CultureInfo.InvariantCulture; } // This needs to work before source is attached. return new CultureInfo((short)NativeMethods.IntPtrToInt32(hkl)); } set { if (value == null) { throw new ArgumentNullException("value"); } SetSourceCurrentLanguageId(value); } } ////// Return enumerator for available input languages. /// public IEnumerable AvailableInputLanguages { get { if (_source == null) { return null; } return (IEnumerable)_source.InputLanguageList; } } //----------------------------------------------------- // // Public Events // //----------------------------------------------------- ////// This is an event when the input language is changed. /// public event InputLanguageEventHandler InputLanguageChanged { add { if (value == null) { throw new ArgumentNullException("value"); } if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Initialize(); _InputLanguageChanged += value; } remove { if (value == null) { throw new ArgumentNullException("value"); } _InputLanguageChanged -= value; if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Uninitialize(); } } ////// This is an event when the input language is being changed. /// public event InputLanguageEventHandler InputLanguageChanging { add { if (value == null) { throw new ArgumentNullException("value"); } if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Initialize(); _InputLanguageChanging += value; } remove { if (value == null) { throw new ArgumentNullException("value"); } _InputLanguageChanging -= value; if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Uninitialize(); } } //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// When keyboard device gets focus, this is called. /// We will check the preferred input language of focus element. /// internal void Focus(DependencyObject focus, DependencyObject focused) { CultureInfo culture = null; if (focus != null) { // // Check the InputLanguageProperty of the focus element. // culture = (CultureInfo)focus.GetValue(InputLanguageProperty); } if ((culture == null) || (culture.Equals(CultureInfo.InvariantCulture))) { // // If the focus element does not have InputLanguage property, // we may need to restore the previous input language. // if (focused != null) { if ((_previousLanguageId != null) && (bool)focused.GetValue(RestoreInputLanguageProperty)) { // // set the current language id of source. // SetSourceCurrentLanguageId(_previousLanguageId); } _previousLanguageId = null; } } else { // Cache the previous language id. // _previousLanguageId can be clear during SetSourceCurrentLanguageId() because the call back // ReportInputLanguageChanged() is called. We need to remember the current input language // to update _previousLanguageId. CultureInfo previousLanguageId = _source.CurrentInputLanguage; // // set the current language id of source. // SetSourceCurrentLanguageId(culture); _previousLanguageId = previousLanguageId; } } #endregion Internal methods //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties internal IInputLanguageSource Source { get { return _source; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- private void SetSourceCurrentLanguageId(CultureInfo languageId) { if (_source == null) { throw new InvalidOperationException(SR.Get(SRID.InputLanguageManager_NotReadyToChangeCurrentLanguage)); } _source.CurrentInputLanguage = languageId; } //----------------------------------------------------- // // Private Properties // //----------------------------------------------------- ////// This checks if there is two or more keyboard layouts. /// private bool IsMultipleKeyboardLayout { get { int count = SafeNativeMethods.GetKeyboardLayoutList(0, null); return (count > 1); } } //------------------------------------------------------ // // Private Events // //----------------------------------------------------- ////// This is an event when the input language is changed. /// private event InputLanguageEventHandler _InputLanguageChanged; ////// This is an event when the input language is being changed. /// private event InputLanguageEventHandler _InputLanguageChanging; //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ #region Private Fields // the previous input language id this is used for restring input language at // losing focus. private CultureInfo _previousLanguageId; // The reference to the source of input language. private IInputLanguageSource _source; #endregion Private Fields } ////// This is a delegate for InputLanguageChanged and /// InputLanguageChanging events. /// public delegate void InputLanguageEventHandler(Object sender, InputLanguageEventArgs e); } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: InputLanguageManager class and InputLanguage APIs. // // History: // 07/30/2003 : yutakas - ported from dotnet tree. // //--------------------------------------------------------------------------- using System.Collections; using System.Windows.Threading; using System.Windows; using System.Globalization; using MS.Win32; using System; using System.Security; using System.Runtime.InteropServices; using System.ComponentModel; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Input { ////// The InputLanguageManager class is responsible for mmanaging /// the input language in Avalon. /// public sealed class InputLanguageManager : DispatcherObject { ////// This is the property of the preferred input language of the /// element. /// When the element get focus, this input language is selected /// automatically. /// public static readonly DependencyProperty InputLanguageProperty = DependencyProperty.RegisterAttached( "InputLanguage", typeof(CultureInfo), typeof(InputLanguageManager), new PropertyMetadata(CultureInfo.InvariantCulture) ); ////// Setter for InputLanguage DependencyProperty /// public static void SetInputLanguage(DependencyObject target, CultureInfo inputLanguage) { if (target == null) { throw new ArgumentNullException("target"); } target.SetValue(InputLanguageProperty, inputLanguage); } ////// Getter for InputLanguage DependencyProperty /// [AttachedPropertyBrowsableForType(typeof(DependencyObject))] [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))] public static CultureInfo GetInputLanguage(DependencyObject target) { if (target == null) { throw new ArgumentNullException("target"); } return (CultureInfo)(target.GetValue(InputLanguageProperty)); } ////// If this is true, the previous inputlanguage is restored /// when the element with InputLanguage dynamicproperty lose the focus. /// This property is ignored if InputLanguage dynamic property is /// not available in the element. /// public static readonly DependencyProperty RestoreInputLanguageProperty = DependencyProperty.RegisterAttached( "RestoreInputLanguage", typeof(bool), typeof(InputLanguageManager), new PropertyMetadata(false) ); ////// Setter for RestoreInputLanguage DependencyProperty /// public static void SetRestoreInputLanguage(DependencyObject target, bool restore) { if (target == null) { throw new ArgumentNullException("target"); } target.SetValue(RestoreInputLanguageProperty, restore); } ////// Getter for RestoreInputLanguage DependencyProperty /// [AttachedPropertyBrowsableForType(typeof(DependencyObject))] public static bool GetRestoreInputLanguage(DependencyObject target) { if (target == null) { throw new ArgumentNullException("target"); } return (bool)(target.GetValue(RestoreInputLanguageProperty)); } //----------------------------------------------------- // // Constructors // //----------------------------------------------------- private InputLanguageManager() { // register our default input language source. RegisterInputLanguageSource(new InputLanguageSource(this)); } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods ////// Registers an input language soruces with the input /// input language manager. /// /// /// The input language source to register. /// public void RegisterInputLanguageSource(IInputLanguageSource inputLanguageSource) { if (inputLanguageSource == null) { throw new ArgumentNullException("inputLanguageSource"); } _source = inputLanguageSource; if (((_InputLanguageChanged != null) || (_InputLanguageChanging != null)) && IsMultipleKeyboardLayout) _source.Initialize(); return; } ////// Report the input language is changed from the source. /// /// /// The new language id. /// /// /// The previous language id. /// public void ReportInputLanguageChanged( CultureInfo newLanguageId, CultureInfo previousLanguageId) { if (newLanguageId == null) { throw new ArgumentNullException("newLanguageId"); } if (previousLanguageId == null) { throw new ArgumentNullException("previousLanguageId"); } // // if this language change was not done by SetFocus() and // InputLanguage Property of the element, we clear _previousLanguageId. // if (!previousLanguageId.Equals(_previousLanguageId)) { _previousLanguageId = null; } if (_InputLanguageChanged != null) { InputLanguageChangedEventArgs args = new InputLanguageChangedEventArgs(newLanguageId, previousLanguageId); // Stability Review: Task#32416 // - No state to be restored even exception happens while this callback. _InputLanguageChanged(this, args); } } ////// Report the input language is being changed from the source. /// /// /// The new language id. /// /// /// The previous language id. /// public bool ReportInputLanguageChanging( CultureInfo newLanguageId, CultureInfo previousLanguageId) { if (newLanguageId == null) { throw new ArgumentNullException("newLanguageId"); } if (previousLanguageId == null) { throw new ArgumentNullException("previousLanguageId"); } bool accepted = true; if (_InputLanguageChanging != null) { InputLanguageChangingEventArgs args = new InputLanguageChangingEventArgs(newLanguageId, previousLanguageId); // Stability Review: Task#32416 // - No state to be restored even exception happens while this callback. _InputLanguageChanging(this, args); accepted = args.Rejected ? false : true; } return accepted; } #endregion Public Methods //------------------------------------------------------ // // Public Operators // //------------------------------------------------------ //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ ////// Return the input language manager associated /// with the current context. /// public static InputLanguageManager Current { get { // InputLanguageManager for the current Dispatcher is stored in InputMethod of // the current Dispatcher. if(InputMethod.Current.InputLanguageManager == null) { InputMethod.Current.InputLanguageManager = new InputLanguageManager(); } return InputMethod.Current.InputLanguageManager; } } ////// This accesses the input language associated /// with the current context. /// [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))] public CultureInfo CurrentInputLanguage { get { // If the source is available, we should use it. if (_source != null) { return _source.CurrentInputLanguage; } IntPtr hkl = SafeNativeMethods.GetKeyboardLayout(0); if (hkl == IntPtr.Zero) { return CultureInfo.InvariantCulture; } // This needs to work before source is attached. return new CultureInfo((short)NativeMethods.IntPtrToInt32(hkl)); } set { if (value == null) { throw new ArgumentNullException("value"); } SetSourceCurrentLanguageId(value); } } ////// Return enumerator for available input languages. /// public IEnumerable AvailableInputLanguages { get { if (_source == null) { return null; } return (IEnumerable)_source.InputLanguageList; } } //----------------------------------------------------- // // Public Events // //----------------------------------------------------- ////// This is an event when the input language is changed. /// public event InputLanguageEventHandler InputLanguageChanged { add { if (value == null) { throw new ArgumentNullException("value"); } if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Initialize(); _InputLanguageChanged += value; } remove { if (value == null) { throw new ArgumentNullException("value"); } _InputLanguageChanged -= value; if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Uninitialize(); } } ////// This is an event when the input language is being changed. /// public event InputLanguageEventHandler InputLanguageChanging { add { if (value == null) { throw new ArgumentNullException("value"); } if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Initialize(); _InputLanguageChanging += value; } remove { if (value == null) { throw new ArgumentNullException("value"); } _InputLanguageChanging -= value; if ((_InputLanguageChanged == null) && (_InputLanguageChanging == null) && IsMultipleKeyboardLayout && (_source != null)) _source.Uninitialize(); } } //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// When keyboard device gets focus, this is called. /// We will check the preferred input language of focus element. /// internal void Focus(DependencyObject focus, DependencyObject focused) { CultureInfo culture = null; if (focus != null) { // // Check the InputLanguageProperty of the focus element. // culture = (CultureInfo)focus.GetValue(InputLanguageProperty); } if ((culture == null) || (culture.Equals(CultureInfo.InvariantCulture))) { // // If the focus element does not have InputLanguage property, // we may need to restore the previous input language. // if (focused != null) { if ((_previousLanguageId != null) && (bool)focused.GetValue(RestoreInputLanguageProperty)) { // // set the current language id of source. // SetSourceCurrentLanguageId(_previousLanguageId); } _previousLanguageId = null; } } else { // Cache the previous language id. // _previousLanguageId can be clear during SetSourceCurrentLanguageId() because the call back // ReportInputLanguageChanged() is called. We need to remember the current input language // to update _previousLanguageId. CultureInfo previousLanguageId = _source.CurrentInputLanguage; // // set the current language id of source. // SetSourceCurrentLanguageId(culture); _previousLanguageId = previousLanguageId; } } #endregion Internal methods //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties internal IInputLanguageSource Source { get { return _source; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- private void SetSourceCurrentLanguageId(CultureInfo languageId) { if (_source == null) { throw new InvalidOperationException(SR.Get(SRID.InputLanguageManager_NotReadyToChangeCurrentLanguage)); } _source.CurrentInputLanguage = languageId; } //----------------------------------------------------- // // Private Properties // //----------------------------------------------------- ////// This checks if there is two or more keyboard layouts. /// private bool IsMultipleKeyboardLayout { get { int count = SafeNativeMethods.GetKeyboardLayoutList(0, null); return (count > 1); } } //------------------------------------------------------ // // Private Events // //----------------------------------------------------- ////// This is an event when the input language is changed. /// private event InputLanguageEventHandler _InputLanguageChanged; ////// This is an event when the input language is being changed. /// private event InputLanguageEventHandler _InputLanguageChanging; //------------------------------------------------------ // // Private Fields // //------------------------------------------------------ #region Private Fields // the previous input language id this is used for restring input language at // losing focus. private CultureInfo _previousLanguageId; // The reference to the source of input language. private IInputLanguageSource _source; #endregion Private Fields } ////// This is a delegate for InputLanguageChanged and /// InputLanguageChanging events. /// public delegate void InputLanguageEventHandler(Object sender, InputLanguageEventArgs e); } // 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
- Group.cs
- MaskedTextProvider.cs
- ImportFileRequest.cs
- AssertSection.cs
- MenuItemStyleCollection.cs
- DebugInfoGenerator.cs
- XmlDataSourceNodeDescriptor.cs
- Primitive.cs
- BitmapFrameDecode.cs
- RSAOAEPKeyExchangeDeformatter.cs
- ChangesetResponse.cs
- _NegotiateClient.cs
- OptimalBreakSession.cs
- FixUp.cs
- SelectedGridItemChangedEvent.cs
- TextContainer.cs
- AttachedAnnotation.cs
- RowToParametersTransformer.cs
- Debug.cs
- SkinBuilder.cs
- ByteAnimationUsingKeyFrames.cs
- HotCommands.cs
- OleAutBinder.cs
- StructuralObject.cs
- Stackframe.cs
- ProfessionalColorTable.cs
- ActivityExecutorDelegateInfo.cs
- TabletDeviceInfo.cs
- ResourceContainer.cs
- NativeMethods.cs
- KeyedHashAlgorithm.cs
- TextBoxLine.cs
- XDeferredAxisSource.cs
- BuildResult.cs
- MenuCommands.cs
- GridViewUpdatedEventArgs.cs
- Comparer.cs
- LogWriteRestartAreaState.cs
- TemplateControlBuildProvider.cs
- RelativeSource.cs
- TextEditor.cs
- ValidationRuleCollection.cs
- SafeFileMapViewHandle.cs
- Lease.cs
- SelectionProcessor.cs
- CodeTypeReferenceExpression.cs
- MimeBasePart.cs
- Crypto.cs
- RuntimeArgumentHandle.cs
- TaiwanCalendar.cs
- Timer.cs
- AbstractExpressions.cs
- ItemsControlAutomationPeer.cs
- SurrogateChar.cs
- CommentEmitter.cs
- MinMaxParagraphWidth.cs
- HeaderUtility.cs
- XpsInterleavingPolicy.cs
- TableHeaderCell.cs
- RoleManagerEventArgs.cs
- WsatTransactionFormatter.cs
- DataGridViewCellErrorTextNeededEventArgs.cs
- XmlSchemaSimpleType.cs
- DataGridViewCellCollection.cs
- TraceContextRecord.cs
- BookmarkUndoUnit.cs
- ArrayTypeMismatchException.cs
- LineBreak.cs
- TemplateBamlTreeBuilder.cs
- PostBackOptions.cs
- RootBrowserWindowProxy.cs
- FieldTemplateUserControl.cs
- XmlCountingReader.cs
- IIS7WorkerRequest.cs
- ConfigurationSection.cs
- MembershipValidatePasswordEventArgs.cs
- MsmqIntegrationAppDomainProtocolHandler.cs
- printdlgexmarshaler.cs
- DerivedKeySecurityToken.cs
- ApplicationManager.cs
- FixedSOMPage.cs
- RequestCachePolicyConverter.cs
- dataSvcMapFileLoader.cs
- _DisconnectOverlappedAsyncResult.cs
- KnownBoxes.cs
- HttpPostedFile.cs
- AnnotationComponentManager.cs
- KeySpline.cs
- OleDbDataReader.cs
- SafeSerializationManager.cs
- ObjectStateEntryBaseUpdatableDataRecord.cs
- SecurityException.cs
- WorkflowServiceHostFactory.cs
- NavigationPropertyEmitter.cs
- DataPagerFieldCollection.cs
- AdapterUtil.cs
- RadioButton.cs
- DataGridViewCellEventArgs.cs
- UserPreferenceChangedEventArgs.cs
- ColumnTypeConverter.cs