TypeBrowser.xaml.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / View / TypeBrowser.xaml.cs / 1477082 / TypeBrowser.xaml.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.View
{ 
    using System;
    using System.Collections.ObjectModel; 
    using System.ComponentModel; 
    using System.IO;
    using System.Linq; 
    using System.Reflection;
    using System.Windows;
    using System.Windows.Automation.Peers;
    using System.Windows.Controls; 
    using System.Windows.Input;
    using System.Collections.Specialized; 
    using System.Collections.Generic; 
    using System.Diagnostics.CodeAnalysis;
    using System.Text; 
    using System.ComponentModel.Design;
    using System.Activities.Presentation.Hosting;
    using System.Windows.Threading;
 
    internal sealed partial class TypeBrowser : DialogWindow
    { 
        static readonly DependencyProperty SelectedTypeProperty = 
            DependencyProperty.Register("SelectedType",
            typeof(Type), 
            typeof(TypeBrowser),
            new UIPropertyMetadata());

        static readonly DependencyProperty HasGenericTypesProperty = 
            DependencyProperty.Register("HasGenericTypes",
            typeof(bool), 
            typeof(TypeBrowser)); 

        static readonly DependencyProperty GenericTypeNameProperty = 
            DependencyProperty.Register("GenericTypeName",
            typeof(String),
            typeof(TypeBrowser));
 
        static readonly DependencyProperty GenericTypeMappingProperty =
            DependencyProperty.Register("GenericTypeMapping", 
            typeof(ObservableCollection), 
            typeof(TypeBrowser));
 


        static readonly DependencyProperty ConcreteTypeProperty =
            DependencyProperty.Register("ConcreteType", 
            typeof(Type),
            typeof(TypeBrowser)); 
 
        static Size size = Size.Empty;
 
        SearchAction currentSearch = null;

        ObservableCollection localAssemblies;
        ObservableCollection referenceAssemblies; 
        AssemblyContextControlItem assemblyContext;
        Func filter; 
 
        public TypeBrowser(AssemblyContextControlItem assemblyContext, EditingContext context, Func filter)
        { 
            this.assemblyContext = assemblyContext;
            this.Context = context;
            this.filter = filter;
            SetValue(GenericTypeMappingProperty, new ObservableCollection()); 
            GenericTypeMapping.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(GenericTypeMappingCollectionChanged);
            InitializeComponent(); 
            this.typeEntryTextBox.Focus(); 

            if (!size.IsEmpty) 
            {
                this.Height = size.Height;
                this.Width = size.Width;
            } 

            this.SizeChanged += new SizeChangedEventHandler(TypeBrowser_SizeChanged); 
 
            this.HelpKeyword = HelpKeywords.TypeBrowser;
        } 

        static void TypeBrowser_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            TypeBrowser.size = e.NewSize; 
        }
 
        Type SelectedType 
        {
            get { return (Type)GetValue(SelectedTypeProperty); } 
            set { SetValue(SelectedTypeProperty, value); }
        }

        bool HasGenericTypes 
        {
            get { return (bool)GetValue(HasGenericTypesProperty); } 
            set { SetValue(HasGenericTypesProperty, value); } 
        }
 
        string GenericTypeName
        {
            get { return (string)GetValue(GenericTypeNameProperty); }
            set { SetValue(GenericTypeNameProperty, value); } 
        }
 
        ObservableCollection GenericTypeMapping 
        {
            get { return (ObservableCollection)GetValue(GenericTypeMappingProperty); } 
            set { SetValue(GenericTypeMappingProperty, value); }
        }

        public Type ConcreteType 
        {
            get { return (Type)GetValue(ConcreteTypeProperty); } 
            private set { SetValue(ConcreteTypeProperty, value); } 
        }
 
        public ObservableCollection LocalAssemblies
        {
            get
            { 
                if (null == this.localAssemblies)
                { 
                    this.localAssemblies = new ObservableCollection(); 
                    if (null != this.assemblyContext)
                    { 
                        if (null != this.assemblyContext.LocalAssemblyName)
                        {
                            IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService();
                            Assembly local = AssemblyContextControlItem.GetAssembly(this.assemblyContext.LocalAssemblyName, multiTargetingSupportService); 
                            if (local != null)
                            { 
                                this.localAssemblies.Add(new AssemblyNode(local, true, this.filter, this.Context)); 
                            }
                        } 
                    }

                    if (this.localAssemblies.Count == 0)
                    { 
                        this.LocalAssembly.Visibility = Visibility.Collapsed;
                    } 
                    else 
                    {
                        this.LocalAssembly.Visibility = Visibility.Visible; 
                    }
                }
                return this.localAssemblies;
            } 
        }
 
        public ObservableCollection ReferenceAssemblies 
        {
            get 
            {
                if (null == this.referenceAssemblies)
                {
                    this.referenceAssemblies = new ObservableCollection(); 
                    if (null != this.assemblyContext)
                    { 
                        IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService(); 
                        IEnumerable assemblies = this.assemblyContext.GetEnvironmentAssemblies(multiTargetingSupportService);
                        foreach (Assembly assembly in assemblies.OrderBy(p => p.FullName)) 
                        {
                            this.referenceAssemblies.Add(new AssemblyNode(assembly, false, this.filter, this.Context));
                        }
                    } 
                }
                return this.referenceAssemblies; 
            } 
        }
 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            { 
                this.DialogResult = false;
                e.Handled = true; 
            } 
            else if (e.Key == Key.Enter && null != SelectedType)
            { 
                OnDialogClose();
                e.Handled = true;
            }
            else 
            {
                base.OnKeyDown(e); 
            } 
        }
 
        protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
        {
            return new UIElementAutomationPeer(this);
        } 

        private void GenericTypeMappingCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
        { 
            this.HasGenericTypes = GenericTypeMapping.Count > 0 ? true : false;
            if (this.HasGenericTypes) 
            {
                string strName = this.SelectedType.FullName;
                this.GenericTypeName = strName.Substring(0, strName.Length - 2) + " <";
            } 
            else
            { 
                this.GenericTypeName = null; 
            }
        } 

        private Type ResolveType(out string errorTitle, out string errorMessage)
        {
            errorTitle = null; 
            errorMessage = null;
            Type result = this.SelectedType; 
 
            try
            { 
                IMultiTargetingSupportService multiTargetingSupport = this.Context.Services.GetService();
                if (multiTargetingSupport != null)
                {
                    result = multiTargetingSupport.GetRuntimeType(result); 
                }
 
                if (result == null) 
                {
                    errorTitle = SR.TypeBrowserErrorMessageTitle; 
                    errorMessage = SR.TypeBrowserError;
                    return null;
                }
 
                if (result.IsGenericTypeDefinition)
                { 
                    bool isValid = true; 
                    //get number of generic parameters in edited type
                    Type[] arguments = new Type[this.GenericTypeMapping.Count]; 

                    //for each argument, get resolved type
                    for (int i = 0; i < this.GenericTypeMapping.Count && isValid; ++i)
                    { 
                        arguments[i] = this.GenericTypeMapping[i].GetConcreteType();
                        if (multiTargetingSupport != null && arguments[i] != null) 
                        { 
                            arguments[i] = multiTargetingSupport.GetRuntimeType(arguments[i]);
                        } 
                        isValid = isValid && (null != arguments[i]);
                    }

                    //if all parameters are resolved, create concrete type 
                    if (isValid)
                    { 
                        result = result.MakeGenericType(arguments); 
                    }
                    else 
                    {
                        errorTitle = SR.TypeBrowserErrorMessageTitle;
                        errorMessage = SR.TypeResolverError;
                        result = null; 
                    }
                } 
            } 
            catch (ArgumentException err)
            { 
                errorTitle = err.GetType().Name;
                errorMessage = err.Message;
                return null;
            } 

            return result; 
        } 

        private void OnOkClick(object sender, RoutedEventArgs args) 
        {
            OnDialogClose();
        }
 
        private void OnCancelClick(object sender, RoutedEventArgs args)
        { 
            this.DialogResult = false; 
        }
 
        private void OnTypeDoubleClick(object sender, RoutedEventArgs args)
        {
            if (((System.Windows.Input.MouseButtonEventArgs)(args)).ChangedButton == MouseButton.Left)
            { 
                TypeNode entry = ((TreeViewItem)sender).Header as TypeNode;
                if (null != entry && entry.Data is Type) 
                { 
                    OnDialogClose();
                    args.Handled = true; 
                }
            }
        }
 
        private void OnDialogClose()
        { 
            string errorTitle = null; 
            string errorMessage = null;
 
            Type type = ResolveType(out errorTitle, out errorMessage);
            if (null != type)
            {
                this.ConcreteType = type; 
                this.DialogResult = true;
            } 
            else 
            {
                MessageBox.Show(errorMessage, errorTitle, MessageBoxButton.OK, MessageBoxImage.Error); 
            }
        }

        private void OnTypeBrowserClickStart(object sender, RoutedEventArgs args) 
        {
            TreeViewItem item = sender as TreeViewItem; 
            NamespaceNode ns = null; 
            if (null != item)
            { 
                ns = item.Header as NamespaceNode;
            }

            if (null != ns && null == ns.Tag) 
            {
                ns.Tag = string.Empty; 
                Mouse.OverrideCursor = Cursors.Wait; 
            }
        } 

        private void OnTypeBrowserClickEnd(object sender, RoutedEventArgs args)
        {
            TreeViewItem item = sender as TreeViewItem; 
            if (null != item && item.Header is AssemblyNode && null != Mouse.OverrideCursor)
            { 
                Mouse.OverrideCursor = null; 
            }
        } 

        private void OnTypeSearchTextChanged(object sender, TextChangedEventArgs e)
        {
            string searchText = ((TextBox)sender).Text; 

            SearchAction newSearch = new SearchAction(searchText, this.localAssemblies, this.referenceAssemblies); 
            newSearch.Completed += delegate(object s, EventArgs args) 
            {
                SearchAction senderAction = s as SearchAction; 
                SearchAction currentAction = this.currentSearch;
                this.currentSearch = null;

                if (senderAction == currentAction) 
                {
                    TypeNode match = ((SearchActionEventArgs)args).Result as TypeNode; 
 
                    UpdateSelectedItem(match);
                    if (match != null) 
                    {
                        match.IsSelected = true;
                    }
                } 
            };
 
            if (this.currentSearch != null) 
            {
                this.currentSearch.Abort(); 
            }

            ClearSelection();
 
            this.currentSearch = newSearch;
            this.currentSearch.Run(); 
        } 

        private void ClearSelection() 
        {
            TypeNode currentSelection = this.typesTreeView.SelectedItem as TypeNode;
            if (currentSelection != null)
            { 
                currentSelection.IsSelected = false;
            } 
        } 

        private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) 
        {
            TypeNode entry = ((TreeView)sender).SelectedItem as TypeNode;
            if (entry != null && this.SelectedType != entry.Data as Type)
            { 
                UpdateSelectedItem(entry);
                if (null != this.SelectedType) 
                { 
                    typeEntryTextBox.TextChanged -= new TextChangedEventHandler(OnTypeSearchTextChanged);
                    typeEntryTextBox.Text = TypeNameHelper.GetDisplayName(this.SelectedType, true); 
                    typeEntryTextBox.TextChanged += new TextChangedEventHandler(OnTypeSearchTextChanged);
                }
            }
        } 

        private void UpdateSelectedItem(TypeNode entry) 
        { 
            GenericTypeMapping.Clear();
 
            SelectedType = (null != entry ? entry.Data as Type : null);

            if (null != this.SelectedType)
            { 
                if (this.SelectedType.IsGenericTypeDefinition)
                { 
                    this.ConcreteType = null; 
                    Type[] generics = this.SelectedType.GetGenericArguments();
                    foreach (Type t in generics) 
                    {
                        this.GenericTypeMapping.Add(new TypeKeyValue(t, null));
                    }
                } 
                else
                { 
                    this.ConcreteType = this.SelectedType; 
                }
            } 
            else
            {
                this.ConcreteType = null;
            } 
        }
 
        internal class Node : INotifyPropertyChanged 
        {
            public event PropertyChangedEventHandler PropertyChanged; 

            private bool isExpanded;
            private bool isSelected;
            private Visibility visibility; 

            protected Node() 
            { 
                this.isExpanded = false;
                this.isSelected = false; 
                this.visibility = Visibility.Visible;
            }

            protected void Notify(string property) 
            {
                if (PropertyChanged != null) 
                { 
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
                } 
            }

            public bool IsExpanded
            { 
                get
                { 
                    return this.isExpanded; 
                }
                set 
                {
                    if (this.isExpanded != value)
                    {
                        this.isExpanded = value; 
                        Notify("IsExpanded");
                    } 
                } 
            }
 
            public bool IsSelected
            {
                get
                { 
                    return this.isSelected;
                } 
                set 
                {
                    if (this.isSelected != value) 
                    {
                        this.isSelected = value;
                        Notify("IsSelected");
                    } 
                }
            } 
 
            public Visibility Visibility
            { 
                get
                {
                    return this.visibility;
                } 
                set
                { 
                    if (this.visibility != value) 
                    {
                        this.visibility = value; 
                        Notify("Visibility");
                    }
                }
            } 

            public object Tag 
            { 
                get;
                set; 
            }
        }

        internal class AssemblyNode : Node 
        {
            string displayName; 
            Assembly assembly; 
            bool isLocal;
            Func filter; 
            EditingContext context;

            public AssemblyNode(Assembly assembly, bool isLocal, Func filter, EditingContext context)
            { 
                if (null == assembly)
                { 
                    throw FxTrace.Exception.AsError(new ArgumentNullException("assembly")); 
                }
                this.assembly = assembly; 
                this.isLocal = isLocal;
                this.displayName = GetDisplayName(this.assembly.GetName());
                this.filter = filter;
                this.context = context; 
            }
 
            private static string GetDisplayName(AssemblyName name) 
            {
                StringBuilder sb = new StringBuilder(); 
                if (name != null && name.Name != null)
                {
                    sb.Append(name.Name);
                    if (name.Version != null) 
                    {
                        sb.Append(" ["); 
                        sb.Append(name.Version.Major); 
                        sb.Append(".");
                        sb.Append(name.Version.Minor); 
                        sb.Append(".");
                        sb.Append(name.Version.Build);
                        sb.Append(".");
                        sb.Append(name.Version.Revision); 
                        sb.Append("]");
                    } 
                } 
                return sb.ToString();
            } 

            public string DisplayName
            {
                get { return this.displayName; } 
            }
 
            private ObservableCollection namespaces; 
            public ObservableCollection Namespaces
            { 
                get
                {
                    if (namespaces == null)
                    { 
                        namespaces = new ObservableCollection();
 
                        try 
                        {
                            Func typeFilter = this.filter; 
                            IMultiTargetingSupportService multiTargetingSupport = this.context.Services.GetService();
                            if (multiTargetingSupport != null && typeFilter != null)
                            {
                                typeFilter = (type)=> this.filter(multiTargetingSupport.GetRuntimeType(type)); 
                            }
 
                            var exportedTypes = 
                                from type in (this.isLocal ? this.assembly.GetTypes() : this.assembly.GetExportedTypes())
                                where (type.IsPublic && type.IsVisible && (typeFilter == null || typeFilter(type))) 
                                orderby type.Namespace, type.Name
                                select type;

                            NamespaceNode lastNamespace = null; 
                            foreach (Type type in exportedTypes)
                            { 
                                if (lastNamespace == null || !StringComparer.OrdinalIgnoreCase.Equals(lastNamespace.DisplayName, type.Namespace)) 
                                {
                                    lastNamespace = new NamespaceNode(type.Namespace); 
                                    namespaces.Add(lastNamespace);
                                }

                                lastNamespace.Types.Add(new TypeNode(type)); 
                            }
                        } 
                        catch (NotSupportedException) 
                        {
                            //Dynamic (in memory) assemblies will throw exception when this method is called 
                            //that's the reason i'm swollowing that exception
                        }

                    } 
                    return namespaces;
                } 
            } 

            public string Data 
            {
                get { return this.displayName; }
            }
 
            public override string ToString()
            { 
                return this.displayName; 
            }
        } 

        internal class NamespaceNode : Node
        {
 
            private string displayName;
            public string DisplayName 
            { 
                get
                { 
                    return this.displayName;
                }
            }
 
            private ObservableCollection types;
            public ObservableCollection Types 
            { 
                get
                { 
                    return this.types;
                }
            }
 
            public string Data
            { 
                get { return this.displayName; } 
            }
 
            public NamespaceNode(string name)
            {
                this.displayName = name;
                this.types = new ObservableCollection(); 
            }
        } 
 
        internal class TypeNode : Node
        { 
            private Type type;

            private string displayName;
            public string DisplayName 
            {
                get 
                { 
                    return this.displayName;
                } 
            }

            private string fullName;
            public string FullName 
            {
                get 
                { 
                    return this.fullName;
                } 
            }

            public Type Data
            { 
                get { return this.type; }
            } 
 
            public TypeNode(Type type)
            { 
                this.type = type;
                this.displayName = TypeNameHelper.GetDisplayName(type, false);
                this.fullName = TypeNameHelper.GetDisplayName(type, true);
            } 
        }
 
        private class SearchActionEventArgs : EventArgs 
        {
            public object Result 
            {
                get;
                set;
            } 
        }
 
        private class SearchAction 
        {
            private string searchText; 
            Collection[] range;
            DispatcherOperation dispatcherOperation;

            public event EventHandler Completed; 

            public SearchAction(string searchText, Collection localAssemblies, Collection referenceAssemblies) 
            { 
                this.searchText = searchText;
                this.range = new Collection[] { localAssemblies, referenceAssemblies }; 
            }


            public void Run() 
            {
                this.dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Input, new Func(this.OnRun)); 
                this.dispatcherOperation.Completed += this.OnCompleted; 
            }
 
            public bool Abort()
            {
                if (this.dispatcherOperation != null)
                { 
                    return this.dispatcherOperation.Abort();
                } 
                return true; 
            }
 
            private TypeNode OnRun()
            {
                bool noSearch = string.IsNullOrEmpty(searchText);
                Func matchAlgorithm = SearchAction.MatchShortName; 

                TypeNode match = null; 
                TypeNode firstCandidate = null; 
                bool tooManyCandiates = false;
 
                if (!noSearch && searchText.Contains('.'))
                {
                    matchAlgorithm = SearchAction.MatchFullName;
                } 

                foreach (Collection assemblies in this.range) 
                { 
                    foreach (AssemblyNode assembly in assemblies)
                    { 
                        Visibility assemblyVisibility = Visibility.Collapsed;
                        bool assemblyIsExpanded = false;

                        if (noSearch) 
                        {
                            assemblyVisibility = Visibility.Visible; 
                        } 

                        foreach (NamespaceNode ns in assembly.Namespaces) 
                        {
                            Visibility namespaceVisibility = Visibility.Collapsed;
                            bool namespaceIsExpanded = false;
 
                            if (noSearch)
                            { 
                                namespaceVisibility = Visibility.Visible; 
                            }
 
                            foreach (TypeNode entry in ns.Types)
                            {
                                if (noSearch)
                                { 
                                    entry.Visibility = Visibility.Visible;
                                } 
                                else if (matchAlgorithm(entry, searchText)) 
                                {
                                    entry.Visibility = Visibility.Visible; 
                                    assemblyVisibility = Visibility.Visible;
                                    assemblyIsExpanded = true;
                                    namespaceVisibility = Visibility.Visible;
                                    namespaceIsExpanded = true; 

                                    if (string.Equals(searchText, entry.FullName, StringComparison.OrdinalIgnoreCase)) 
                                    { 
                                        match = entry;
                                    } 

                                    if (firstCandidate == null)
                                    {
                                        firstCandidate = entry; 
                                    }
                                    else if (!tooManyCandiates) 
                                    { 
                                        tooManyCandiates = true;
                                    } 
                                }
                                else
                                {
                                    entry.Visibility = Visibility.Collapsed; 
                                }
                            } 
 
                            if (searchText.Contains('.') && ns.DisplayName != null && ns.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase))
                            { 
                                namespaceIsExpanded = false;
                            }

                            if (namespaceIsExpanded) 
                            {
                                ns.Tag = string.Empty; 
                            } 

                            ns.Visibility = namespaceVisibility; 
                            ns.IsExpanded = namespaceIsExpanded;
                        }

                        assembly.Visibility = assemblyVisibility; 
                        assembly.IsExpanded = assemblyIsExpanded;
                    } 
                } 

                if (match == null && !tooManyCandiates) 
                {
                    match = firstCandidate;
                }
 
                return match;
            } 
 
            private void OnCompleted(object sender, EventArgs args)
            { 
                this.dispatcherOperation.Completed -= this.OnCompleted;
                if (this.Completed != null)
                {
                    SearchActionEventArgs arg = new SearchActionEventArgs(); 
                    arg.Result = this.dispatcherOperation.Result;
                    this.Completed(this, arg); 
                } 
            }
 
            // "abc.def" matches regex ^.*\.abc\.def.* or ^abc\.def.*, but does not match ^.*[^.]abc\.def.*
            private static bool MatchFullName(TypeNode type, string searchText)
            {
                if (searchText.StartsWith(".", StringComparison.OrdinalIgnoreCase)) 
                {
                    return -1 != type.FullName.IndexOf(searchText, StringComparison.OrdinalIgnoreCase); 
                } 

                if (type.FullName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase)) 
                {
                    return true;
                }
 
                if (-1 != type.FullName.IndexOf("." + searchText, StringComparison.OrdinalIgnoreCase))
                { 
                    return true; 
                }
 
                return false;
            }

            private static bool MatchShortName(TypeNode type, string searchText) 
            {
                return type.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase); 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.View
{ 
    using System;
    using System.Collections.ObjectModel; 
    using System.ComponentModel; 
    using System.IO;
    using System.Linq; 
    using System.Reflection;
    using System.Windows;
    using System.Windows.Automation.Peers;
    using System.Windows.Controls; 
    using System.Windows.Input;
    using System.Collections.Specialized; 
    using System.Collections.Generic; 
    using System.Diagnostics.CodeAnalysis;
    using System.Text; 
    using System.ComponentModel.Design;
    using System.Activities.Presentation.Hosting;
    using System.Windows.Threading;
 
    internal sealed partial class TypeBrowser : DialogWindow
    { 
        static readonly DependencyProperty SelectedTypeProperty = 
            DependencyProperty.Register("SelectedType",
            typeof(Type), 
            typeof(TypeBrowser),
            new UIPropertyMetadata());

        static readonly DependencyProperty HasGenericTypesProperty = 
            DependencyProperty.Register("HasGenericTypes",
            typeof(bool), 
            typeof(TypeBrowser)); 

        static readonly DependencyProperty GenericTypeNameProperty = 
            DependencyProperty.Register("GenericTypeName",
            typeof(String),
            typeof(TypeBrowser));
 
        static readonly DependencyProperty GenericTypeMappingProperty =
            DependencyProperty.Register("GenericTypeMapping", 
            typeof(ObservableCollection), 
            typeof(TypeBrowser));
 


        static readonly DependencyProperty ConcreteTypeProperty =
            DependencyProperty.Register("ConcreteType", 
            typeof(Type),
            typeof(TypeBrowser)); 
 
        static Size size = Size.Empty;
 
        SearchAction currentSearch = null;

        ObservableCollection localAssemblies;
        ObservableCollection referenceAssemblies; 
        AssemblyContextControlItem assemblyContext;
        Func filter; 
 
        public TypeBrowser(AssemblyContextControlItem assemblyContext, EditingContext context, Func filter)
        { 
            this.assemblyContext = assemblyContext;
            this.Context = context;
            this.filter = filter;
            SetValue(GenericTypeMappingProperty, new ObservableCollection()); 
            GenericTypeMapping.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(GenericTypeMappingCollectionChanged);
            InitializeComponent(); 
            this.typeEntryTextBox.Focus(); 

            if (!size.IsEmpty) 
            {
                this.Height = size.Height;
                this.Width = size.Width;
            } 

            this.SizeChanged += new SizeChangedEventHandler(TypeBrowser_SizeChanged); 
 
            this.HelpKeyword = HelpKeywords.TypeBrowser;
        } 

        static void TypeBrowser_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            TypeBrowser.size = e.NewSize; 
        }
 
        Type SelectedType 
        {
            get { return (Type)GetValue(SelectedTypeProperty); } 
            set { SetValue(SelectedTypeProperty, value); }
        }

        bool HasGenericTypes 
        {
            get { return (bool)GetValue(HasGenericTypesProperty); } 
            set { SetValue(HasGenericTypesProperty, value); } 
        }
 
        string GenericTypeName
        {
            get { return (string)GetValue(GenericTypeNameProperty); }
            set { SetValue(GenericTypeNameProperty, value); } 
        }
 
        ObservableCollection GenericTypeMapping 
        {
            get { return (ObservableCollection)GetValue(GenericTypeMappingProperty); } 
            set { SetValue(GenericTypeMappingProperty, value); }
        }

        public Type ConcreteType 
        {
            get { return (Type)GetValue(ConcreteTypeProperty); } 
            private set { SetValue(ConcreteTypeProperty, value); } 
        }
 
        public ObservableCollection LocalAssemblies
        {
            get
            { 
                if (null == this.localAssemblies)
                { 
                    this.localAssemblies = new ObservableCollection(); 
                    if (null != this.assemblyContext)
                    { 
                        if (null != this.assemblyContext.LocalAssemblyName)
                        {
                            IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService();
                            Assembly local = AssemblyContextControlItem.GetAssembly(this.assemblyContext.LocalAssemblyName, multiTargetingSupportService); 
                            if (local != null)
                            { 
                                this.localAssemblies.Add(new AssemblyNode(local, true, this.filter, this.Context)); 
                            }
                        } 
                    }

                    if (this.localAssemblies.Count == 0)
                    { 
                        this.LocalAssembly.Visibility = Visibility.Collapsed;
                    } 
                    else 
                    {
                        this.LocalAssembly.Visibility = Visibility.Visible; 
                    }
                }
                return this.localAssemblies;
            } 
        }
 
        public ObservableCollection ReferenceAssemblies 
        {
            get 
            {
                if (null == this.referenceAssemblies)
                {
                    this.referenceAssemblies = new ObservableCollection(); 
                    if (null != this.assemblyContext)
                    { 
                        IMultiTargetingSupportService multiTargetingSupportService = this.Context.Services.GetService(); 
                        IEnumerable assemblies = this.assemblyContext.GetEnvironmentAssemblies(multiTargetingSupportService);
                        foreach (Assembly assembly in assemblies.OrderBy(p => p.FullName)) 
                        {
                            this.referenceAssemblies.Add(new AssemblyNode(assembly, false, this.filter, this.Context));
                        }
                    } 
                }
                return this.referenceAssemblies; 
            } 
        }
 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            { 
                this.DialogResult = false;
                e.Handled = true; 
            } 
            else if (e.Key == Key.Enter && null != SelectedType)
            { 
                OnDialogClose();
                e.Handled = true;
            }
            else 
            {
                base.OnKeyDown(e); 
            } 
        }
 
        protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
        {
            return new UIElementAutomationPeer(this);
        } 

        private void GenericTypeMappingCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
        { 
            this.HasGenericTypes = GenericTypeMapping.Count > 0 ? true : false;
            if (this.HasGenericTypes) 
            {
                string strName = this.SelectedType.FullName;
                this.GenericTypeName = strName.Substring(0, strName.Length - 2) + " <";
            } 
            else
            { 
                this.GenericTypeName = null; 
            }
        } 

        private Type ResolveType(out string errorTitle, out string errorMessage)
        {
            errorTitle = null; 
            errorMessage = null;
            Type result = this.SelectedType; 
 
            try
            { 
                IMultiTargetingSupportService multiTargetingSupport = this.Context.Services.GetService();
                if (multiTargetingSupport != null)
                {
                    result = multiTargetingSupport.GetRuntimeType(result); 
                }
 
                if (result == null) 
                {
                    errorTitle = SR.TypeBrowserErrorMessageTitle; 
                    errorMessage = SR.TypeBrowserError;
                    return null;
                }
 
                if (result.IsGenericTypeDefinition)
                { 
                    bool isValid = true; 
                    //get number of generic parameters in edited type
                    Type[] arguments = new Type[this.GenericTypeMapping.Count]; 

                    //for each argument, get resolved type
                    for (int i = 0; i < this.GenericTypeMapping.Count && isValid; ++i)
                    { 
                        arguments[i] = this.GenericTypeMapping[i].GetConcreteType();
                        if (multiTargetingSupport != null && arguments[i] != null) 
                        { 
                            arguments[i] = multiTargetingSupport.GetRuntimeType(arguments[i]);
                        } 
                        isValid = isValid && (null != arguments[i]);
                    }

                    //if all parameters are resolved, create concrete type 
                    if (isValid)
                    { 
                        result = result.MakeGenericType(arguments); 
                    }
                    else 
                    {
                        errorTitle = SR.TypeBrowserErrorMessageTitle;
                        errorMessage = SR.TypeResolverError;
                        result = null; 
                    }
                } 
            } 
            catch (ArgumentException err)
            { 
                errorTitle = err.GetType().Name;
                errorMessage = err.Message;
                return null;
            } 

            return result; 
        } 

        private void OnOkClick(object sender, RoutedEventArgs args) 
        {
            OnDialogClose();
        }
 
        private void OnCancelClick(object sender, RoutedEventArgs args)
        { 
            this.DialogResult = false; 
        }
 
        private void OnTypeDoubleClick(object sender, RoutedEventArgs args)
        {
            if (((System.Windows.Input.MouseButtonEventArgs)(args)).ChangedButton == MouseButton.Left)
            { 
                TypeNode entry = ((TreeViewItem)sender).Header as TypeNode;
                if (null != entry && entry.Data is Type) 
                { 
                    OnDialogClose();
                    args.Handled = true; 
                }
            }
        }
 
        private void OnDialogClose()
        { 
            string errorTitle = null; 
            string errorMessage = null;
 
            Type type = ResolveType(out errorTitle, out errorMessage);
            if (null != type)
            {
                this.ConcreteType = type; 
                this.DialogResult = true;
            } 
            else 
            {
                MessageBox.Show(errorMessage, errorTitle, MessageBoxButton.OK, MessageBoxImage.Error); 
            }
        }

        private void OnTypeBrowserClickStart(object sender, RoutedEventArgs args) 
        {
            TreeViewItem item = sender as TreeViewItem; 
            NamespaceNode ns = null; 
            if (null != item)
            { 
                ns = item.Header as NamespaceNode;
            }

            if (null != ns && null == ns.Tag) 
            {
                ns.Tag = string.Empty; 
                Mouse.OverrideCursor = Cursors.Wait; 
            }
        } 

        private void OnTypeBrowserClickEnd(object sender, RoutedEventArgs args)
        {
            TreeViewItem item = sender as TreeViewItem; 
            if (null != item && item.Header is AssemblyNode && null != Mouse.OverrideCursor)
            { 
                Mouse.OverrideCursor = null; 
            }
        } 

        private void OnTypeSearchTextChanged(object sender, TextChangedEventArgs e)
        {
            string searchText = ((TextBox)sender).Text; 

            SearchAction newSearch = new SearchAction(searchText, this.localAssemblies, this.referenceAssemblies); 
            newSearch.Completed += delegate(object s, EventArgs args) 
            {
                SearchAction senderAction = s as SearchAction; 
                SearchAction currentAction = this.currentSearch;
                this.currentSearch = null;

                if (senderAction == currentAction) 
                {
                    TypeNode match = ((SearchActionEventArgs)args).Result as TypeNode; 
 
                    UpdateSelectedItem(match);
                    if (match != null) 
                    {
                        match.IsSelected = true;
                    }
                } 
            };
 
            if (this.currentSearch != null) 
            {
                this.currentSearch.Abort(); 
            }

            ClearSelection();
 
            this.currentSearch = newSearch;
            this.currentSearch.Run(); 
        } 

        private void ClearSelection() 
        {
            TypeNode currentSelection = this.typesTreeView.SelectedItem as TypeNode;
            if (currentSelection != null)
            { 
                currentSelection.IsSelected = false;
            } 
        } 

        private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) 
        {
            TypeNode entry = ((TreeView)sender).SelectedItem as TypeNode;
            if (entry != null && this.SelectedType != entry.Data as Type)
            { 
                UpdateSelectedItem(entry);
                if (null != this.SelectedType) 
                { 
                    typeEntryTextBox.TextChanged -= new TextChangedEventHandler(OnTypeSearchTextChanged);
                    typeEntryTextBox.Text = TypeNameHelper.GetDisplayName(this.SelectedType, true); 
                    typeEntryTextBox.TextChanged += new TextChangedEventHandler(OnTypeSearchTextChanged);
                }
            }
        } 

        private void UpdateSelectedItem(TypeNode entry) 
        { 
            GenericTypeMapping.Clear();
 
            SelectedType = (null != entry ? entry.Data as Type : null);

            if (null != this.SelectedType)
            { 
                if (this.SelectedType.IsGenericTypeDefinition)
                { 
                    this.ConcreteType = null; 
                    Type[] generics = this.SelectedType.GetGenericArguments();
                    foreach (Type t in generics) 
                    {
                        this.GenericTypeMapping.Add(new TypeKeyValue(t, null));
                    }
                } 
                else
                { 
                    this.ConcreteType = this.SelectedType; 
                }
            } 
            else
            {
                this.ConcreteType = null;
            } 
        }
 
        internal class Node : INotifyPropertyChanged 
        {
            public event PropertyChangedEventHandler PropertyChanged; 

            private bool isExpanded;
            private bool isSelected;
            private Visibility visibility; 

            protected Node() 
            { 
                this.isExpanded = false;
                this.isSelected = false; 
                this.visibility = Visibility.Visible;
            }

            protected void Notify(string property) 
            {
                if (PropertyChanged != null) 
                { 
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
                } 
            }

            public bool IsExpanded
            { 
                get
                { 
                    return this.isExpanded; 
                }
                set 
                {
                    if (this.isExpanded != value)
                    {
                        this.isExpanded = value; 
                        Notify("IsExpanded");
                    } 
                } 
            }
 
            public bool IsSelected
            {
                get
                { 
                    return this.isSelected;
                } 
                set 
                {
                    if (this.isSelected != value) 
                    {
                        this.isSelected = value;
                        Notify("IsSelected");
                    } 
                }
            } 
 
            public Visibility Visibility
            { 
                get
                {
                    return this.visibility;
                } 
                set
                { 
                    if (this.visibility != value) 
                    {
                        this.visibility = value; 
                        Notify("Visibility");
                    }
                }
            } 

            public object Tag 
            { 
                get;
                set; 
            }
        }

        internal class AssemblyNode : Node 
        {
            string displayName; 
            Assembly assembly; 
            bool isLocal;
            Func filter; 
            EditingContext context;

            public AssemblyNode(Assembly assembly, bool isLocal, Func filter, EditingContext context)
            { 
                if (null == assembly)
                { 
                    throw FxTrace.Exception.AsError(new ArgumentNullException("assembly")); 
                }
                this.assembly = assembly; 
                this.isLocal = isLocal;
                this.displayName = GetDisplayName(this.assembly.GetName());
                this.filter = filter;
                this.context = context; 
            }
 
            private static string GetDisplayName(AssemblyName name) 
            {
                StringBuilder sb = new StringBuilder(); 
                if (name != null && name.Name != null)
                {
                    sb.Append(name.Name);
                    if (name.Version != null) 
                    {
                        sb.Append(" ["); 
                        sb.Append(name.Version.Major); 
                        sb.Append(".");
                        sb.Append(name.Version.Minor); 
                        sb.Append(".");
                        sb.Append(name.Version.Build);
                        sb.Append(".");
                        sb.Append(name.Version.Revision); 
                        sb.Append("]");
                    } 
                } 
                return sb.ToString();
            } 

            public string DisplayName
            {
                get { return this.displayName; } 
            }
 
            private ObservableCollection namespaces; 
            public ObservableCollection Namespaces
            { 
                get
                {
                    if (namespaces == null)
                    { 
                        namespaces = new ObservableCollection();
 
                        try 
                        {
                            Func typeFilter = this.filter; 
                            IMultiTargetingSupportService multiTargetingSupport = this.context.Services.GetService();
                            if (multiTargetingSupport != null && typeFilter != null)
                            {
                                typeFilter = (type)=> this.filter(multiTargetingSupport.GetRuntimeType(type)); 
                            }
 
                            var exportedTypes = 
                                from type in (this.isLocal ? this.assembly.GetTypes() : this.assembly.GetExportedTypes())
                                where (type.IsPublic && type.IsVisible && (typeFilter == null || typeFilter(type))) 
                                orderby type.Namespace, type.Name
                                select type;

                            NamespaceNode lastNamespace = null; 
                            foreach (Type type in exportedTypes)
                            { 
                                if (lastNamespace == null || !StringComparer.OrdinalIgnoreCase.Equals(lastNamespace.DisplayName, type.Namespace)) 
                                {
                                    lastNamespace = new NamespaceNode(type.Namespace); 
                                    namespaces.Add(lastNamespace);
                                }

                                lastNamespace.Types.Add(new TypeNode(type)); 
                            }
                        } 
                        catch (NotSupportedException) 
                        {
                            //Dynamic (in memory) assemblies will throw exception when this method is called 
                            //that's the reason i'm swollowing that exception
                        }

                    } 
                    return namespaces;
                } 
            } 

            public string Data 
            {
                get { return this.displayName; }
            }
 
            public override string ToString()
            { 
                return this.displayName; 
            }
        } 

        internal class NamespaceNode : Node
        {
 
            private string displayName;
            public string DisplayName 
            { 
                get
                { 
                    return this.displayName;
                }
            }
 
            private ObservableCollection types;
            public ObservableCollection Types 
            { 
                get
                { 
                    return this.types;
                }
            }
 
            public string Data
            { 
                get { return this.displayName; } 
            }
 
            public NamespaceNode(string name)
            {
                this.displayName = name;
                this.types = new ObservableCollection(); 
            }
        } 
 
        internal class TypeNode : Node
        { 
            private Type type;

            private string displayName;
            public string DisplayName 
            {
                get 
                { 
                    return this.displayName;
                } 
            }

            private string fullName;
            public string FullName 
            {
                get 
                { 
                    return this.fullName;
                } 
            }

            public Type Data
            { 
                get { return this.type; }
            } 
 
            public TypeNode(Type type)
            { 
                this.type = type;
                this.displayName = TypeNameHelper.GetDisplayName(type, false);
                this.fullName = TypeNameHelper.GetDisplayName(type, true);
            } 
        }
 
        private class SearchActionEventArgs : EventArgs 
        {
            public object Result 
            {
                get;
                set;
            } 
        }
 
        private class SearchAction 
        {
            private string searchText; 
            Collection[] range;
            DispatcherOperation dispatcherOperation;

            public event EventHandler Completed; 

            public SearchAction(string searchText, Collection localAssemblies, Collection referenceAssemblies) 
            { 
                this.searchText = searchText;
                this.range = new Collection[] { localAssemblies, referenceAssemblies }; 
            }


            public void Run() 
            {
                this.dispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Input, new Func(this.OnRun)); 
                this.dispatcherOperation.Completed += this.OnCompleted; 
            }
 
            public bool Abort()
            {
                if (this.dispatcherOperation != null)
                { 
                    return this.dispatcherOperation.Abort();
                } 
                return true; 
            }
 
            private TypeNode OnRun()
            {
                bool noSearch = string.IsNullOrEmpty(searchText);
                Func matchAlgorithm = SearchAction.MatchShortName; 

                TypeNode match = null; 
                TypeNode firstCandidate = null; 
                bool tooManyCandiates = false;
 
                if (!noSearch && searchText.Contains('.'))
                {
                    matchAlgorithm = SearchAction.MatchFullName;
                } 

                foreach (Collection assemblies in this.range) 
                { 
                    foreach (AssemblyNode assembly in assemblies)
                    { 
                        Visibility assemblyVisibility = Visibility.Collapsed;
                        bool assemblyIsExpanded = false;

                        if (noSearch) 
                        {
                            assemblyVisibility = Visibility.Visible; 
                        } 

                        foreach (NamespaceNode ns in assembly.Namespaces) 
                        {
                            Visibility namespaceVisibility = Visibility.Collapsed;
                            bool namespaceIsExpanded = false;
 
                            if (noSearch)
                            { 
                                namespaceVisibility = Visibility.Visible; 
                            }
 
                            foreach (TypeNode entry in ns.Types)
                            {
                                if (noSearch)
                                { 
                                    entry.Visibility = Visibility.Visible;
                                } 
                                else if (matchAlgorithm(entry, searchText)) 
                                {
                                    entry.Visibility = Visibility.Visible; 
                                    assemblyVisibility = Visibility.Visible;
                                    assemblyIsExpanded = true;
                                    namespaceVisibility = Visibility.Visible;
                                    namespaceIsExpanded = true; 

                                    if (string.Equals(searchText, entry.FullName, StringComparison.OrdinalIgnoreCase)) 
                                    { 
                                        match = entry;
                                    } 

                                    if (firstCandidate == null)
                                    {
                                        firstCandidate = entry; 
                                    }
                                    else if (!tooManyCandiates) 
                                    { 
                                        tooManyCandiates = true;
                                    } 
                                }
                                else
                                {
                                    entry.Visibility = Visibility.Collapsed; 
                                }
                            } 
 
                            if (searchText.Contains('.') && ns.DisplayName != null && ns.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase))
                            { 
                                namespaceIsExpanded = false;
                            }

                            if (namespaceIsExpanded) 
                            {
                                ns.Tag = string.Empty; 
                            } 

                            ns.Visibility = namespaceVisibility; 
                            ns.IsExpanded = namespaceIsExpanded;
                        }

                        assembly.Visibility = assemblyVisibility; 
                        assembly.IsExpanded = assemblyIsExpanded;
                    } 
                } 

                if (match == null && !tooManyCandiates) 
                {
                    match = firstCandidate;
                }
 
                return match;
            } 
 
            private void OnCompleted(object sender, EventArgs args)
            { 
                this.dispatcherOperation.Completed -= this.OnCompleted;
                if (this.Completed != null)
                {
                    SearchActionEventArgs arg = new SearchActionEventArgs(); 
                    arg.Result = this.dispatcherOperation.Result;
                    this.Completed(this, arg); 
                } 
            }
 
            // "abc.def" matches regex ^.*\.abc\.def.* or ^abc\.def.*, but does not match ^.*[^.]abc\.def.*
            private static bool MatchFullName(TypeNode type, string searchText)
            {
                if (searchText.StartsWith(".", StringComparison.OrdinalIgnoreCase)) 
                {
                    return -1 != type.FullName.IndexOf(searchText, StringComparison.OrdinalIgnoreCase); 
                } 

                if (type.FullName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase)) 
                {
                    return true;
                }
 
                if (-1 != type.FullName.IndexOf("." + searchText, StringComparison.OrdinalIgnoreCase))
                { 
                    return true; 
                }
 
                return false;
            }

            private static bool MatchShortName(TypeNode type, string searchText) 
            {
                return type.DisplayName.StartsWith(searchText, StringComparison.OrdinalIgnoreCase); 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK