示例#1
0
        static string TryIdentifyFromBinding(List <DependencyObject> tree, DependencyObject obj, BindingExpressionCache cache)
        {
            foreach (var e in cache.GetBindingExpression(obj))
            {
                var path = e.ParentBinding.Path.Path;
                if (string.IsNullOrEmpty(path))
                {
                    continue;
                }

                var  matchExps = new List <BindingExpression>();
                bool objFind   = false;
                foreach (var t in tree)
                {
                    if (t == obj)
                    {
                        objFind = true;
                    }
                    var matchExp = WPFUtility.GetMatchBindingExpression(cache.GetBindingExpression(t), path);
                    if (matchExp != null)
                    {
                        matchExps.Add(matchExp);
                    }
                }
                if (objFind && matchExps.Count == 1)
                {
                    return($".ByBinding(\"{path}\")");
                }
            }
            return(string.Empty);
        }
        static IEnumerable <UIElement> GetChildren(UIElement ctrl)
        {
            var list = new List <UIElement>();

            foreach (var e in WPFUtility.GetLogicalTreeDescendants(ctrl, true, true, 0))
            {
                var element = e as UIElement;
                if (element == null)
                {
                    continue;
                }
                if (!list.Contains(element))
                {
                    list.Add(element);
                }
            }
            foreach (var e in WPFUtility.GetVisualTreeDescendants(ctrl, true, true, 0))
            {
                var element = e as UIElement;
                if (element == null)
                {
                    continue;
                }
                if (!list.Contains(element))
                {
                    list.Add(element);
                }
            }
            return(list);
        }
        private void GetAllWindowAndUserControl(bool isControlTreeOnly, DependencyObject control, Dictionary <Type, DependencyObject> targets, List <Type> getFromControlTreeOnly, List <DependencyObject> recursiveCheck)
        {
            if (control == null)
            {
                return;
            }

            //再帰チェック
            if (CollectionUtility.HasReference(recursiveCheck, control))
            {
                return;
            }
            recursiveCheck.Add(control);

            if ((control is Window) ||
                ((control is UserControl) && (control.GetType() != typeof(UserControl))) ||
                ((control is Page) && (control.GetType() != typeof(Page))))
            {
                targets[control.GetType()] = control;
                if (isControlTreeOnly)
                {
                    getFromControlTreeOnly.Add(control.GetType());
                }

                //Form, UserControlの時はメンバも見る
                foreach (var e in GetFields(control))
                {
                    //まれにGridなどををメンバに持っている場合がある。
                    if (e.Control.GetType().Assembly == typeof(Grid).Assembly)
                    {
                        continue;
                    }

                    GetAllWindowAndUserControl(false, e.Control, targets, getFromControlTreeOnly, recursiveCheck);
                }
            }
            if (!(control is FrameworkElement))
            {
                return;
            }

            foreach (var e in WPFUtility.GetLogicalTreeDescendants(control, true, true, 0))
            {
                GetAllWindowAndUserControl(true, e, targets, getFromControlTreeOnly, recursiveCheck);
            }
            foreach (var e in WPFUtility.GetVisualTreeDescendants(control, true, true, 0))
            {
                GetAllWindowAndUserControl(true, e, targets, getFromControlTreeOnly, recursiveCheck);
            }
        }
示例#4
0
        public IEnumerable <BindingExpression> GetBindingExpression(DependencyObject obj)
        {
            for (int i = 0; i < _objs.Count; i++)
            {
                if (ReferenceEquals(_objs[i], obj))
                {
                    return(_exps[i]);
                }
            }
            _objs.Add(obj);
            var exp = WPFUtility.GetBindingExpression(obj);

            _exps.Add(exp);
            return(exp);
        }
示例#5
0
        private void CreateDriverInfoFindFromControlTree(DependencyObject target, DriverInfo <DependencyObject> driverInfo, List <ControlAndDefine> controlAndDefines, List <DependencyObject> mappedControls, List <string> names, string fileName)
        {
            var logical          = WPFUtility.GetLogicalTreeDescendants(target, true, true, 0);
            var visual           = WPFUtility.GetVisualTreeDescendants(target, true, true, 0);
            var logicalForGetter = WPFUtility.GetLogicalTreeDescendants(target, false, false, 0);
            var visualForGetter  = WPFUtility.GetVisualTreeDescendants(target, false, false, 0);

            foreach (var tree in new[] { logical, visual })
            {
                var cache = new BindingExpressionCache();
                foreach (var ctrl in tree)
                {
                    if (ReferenceEquals(ctrl, target))
                    {
                        continue;
                    }
                    //すでにマップされているかチェック
                    if (CollectionUtility.HasReference(mappedControls, ctrl))
                    {
                        continue;
                    }

                    //コントロールドライバ検索
                    var driver = DriverCreatorUtils.GetDriverTypeFullName(ctrl, DriverCreatorAdapter.TypeFullNameAndControlDriver, DriverCreatorAdapter.TypeFullNameAndUserControlDriver);
                    if (!string.IsNullOrEmpty(driver))
                    {
                        var name      = _customNameGenerator.MakeDriverPropName(ctrl, string.Empty, names);
                        var typeName  = DriverCreatorUtils.GetTypeName(driver);
                        var nameSpace = DriverCreatorUtils.GetTypeNamespace(driver);
                        var getter    = MakeCodeGetFromTree("Core.", logicalForGetter, visualForGetter, ctrl, cache, driverInfo.Usings, out var nogood);
                        var code      = $"public {typeName} {name} => {getter};";
                        if (nogood)
                        {
                            code += $" {TodoComment}";
                        }
                        controlAndDefines.Add(new ControlAndDefine(ctrl, name, code));
                        mappedControls.Add(ctrl);
                        DriverCreatorAdapter.AddCodeLineSelectInfo(fileName, getter, ctrl);
                        if (!driverInfo.Usings.Contains(nameSpace))
                        {
                            driverInfo.Usings.Add(nameSpace);
                        }
                    }
                }
            }
        }
示例#6
0
        internal string GenerateCode(DependencyObject root, DependencyObject targetControl, string nameSpace, string driverClassName, List <string> usings, List <string> members, List <Type> getFromControlTreeOnly)
        {
            foreach (var e in new[]
            {
                "RM.Friendly.WPFStandardControls",
                "Codeer.TestAssistant.GeneratorToolKit",
                "Codeer.Friendly.Windows.Grasp",
                "Codeer.Friendly.Windows",
                "Codeer.Friendly.Dynamic",
                "Codeer.Friendly",
            })
            {
                if (!usings.Contains(e))
                {
                    usings.Insert(0, e);
                }
            }
            var code = new List <string>();

            foreach (var e in usings)
            {
                code.Add($"using {e};");
            }
            int nextUsingIndex = code.Count;

            var existMany = false;

            if (getFromControlTreeOnly.Contains(targetControl.GetType()))
            {
                existMany = WPFUtility.ExistMany(root, targetControl.GetType());
                if (existMany)
                {
                    code.Add("using System.Linq;");
                }
            }

            var attr = (targetControl is Window) ? "WindowDriver" : "UserControlDriver";

            code.Add(string.Empty);
            code.Add($"namespace {nameSpace}");
            code.Add("{");
            code.Add($"{Indent}[{attr}(TypeFullName = \"{targetControl.GetType().FullName}\")]");
            code.Add($"{Indent}public class {driverClassName}");
            code.Add($"{Indent}{{");

            if (targetControl is Window)
            {
                code.Add($"{Indent}{Indent}public WindowControl Core {{ get; }}");
                foreach (var e in members)
                {
                    code.Add($"{Indent}{Indent}{e}");
                }
                code.Add(string.Empty);
                code.Add($"{Indent}{Indent}public {driverClassName}(WindowControl core)");
                code.Add($"{Indent}{Indent}{{");
                code.Add($"{Indent}{Indent}{Indent}Core = core;");
                code.Add($"{Indent}{Indent}}}");
                code.Add(string.Empty);
                code.Add($"{Indent}{Indent}public {driverClassName}(AppVar core)");
                code.Add($"{Indent}{Indent}{{");
                code.Add($"{Indent}{Indent}{Indent}Core = new WindowControl(core);");
                code.Add($"{Indent}{Indent}}}");
            }
            else
            {
                code.Add($"{Indent}{Indent}public WPFUIElement Core {{ get; }}");
                foreach (var e in members)
                {
                    code.Add($"{Indent}{Indent}{e}");
                }
                code.Add(string.Empty);
                code.Add($"{Indent}{Indent}public {driverClassName}(AppVar core)");
                code.Add($"{Indent}{Indent}{{");
                code.Add($"{Indent}{Indent}{Indent}Core = new WPFUIElement(core);");
                code.Add($"{Indent}{Indent}}}");
            }
            code.Add($"{Indent}}}");

            if (getFromControlTreeOnly.Contains(targetControl.GetType()) && !ReferenceEquals(root, targetControl))
            {
                code.Add(string.Empty);
                code.Add($"{Indent}public static class {driverClassName}_Extensions");
                code.Add($"{Indent}{{");
                var funcName   = GetFuncName(driverClassName);
                var rootDriver = _driverTypeNameManager.MakeDriverType(root, out var rootNameSpace);
                if (!string.IsNullOrEmpty(rootNameSpace) && !usings.Contains(rootNameSpace) && (rootNameSpace != nameSpace))
                {
                    code.Insert(nextUsingIndex, $"using {rootNameSpace};");
                }
                if (existMany)
                {
                    code.Add($"{Indent}{Indent}{TodoComment}");
                    code.Add($"{Indent}{Indent}[UserControlDriverIdentify(CustomMethod = \"TryGet\")]");
                    code.Add($"{Indent}{Indent}public static {driverClassName} {funcName}(this {rootDriver} window, int index)");
                    code.Add($"{Indent}{Indent}{Indent}=> new {driverClassName}(window.Core.VisualTree().ByType(\"{targetControl.GetType().FullName}\")[index]);");
                    code.Add(string.Empty);
                    code.Add($"{Indent}{Indent}public static void TryGet(this {rootDriver} window, out int[] indices)");
                    code.Add($"{Indent}{Indent}{Indent}=> indices = Enumerable.Range(0, window.Core.VisualTree().ByType(\"{targetControl.GetType().FullName}\").Count).ToArray();");
                }
                else
                {
                    code.Add($"{Indent}{Indent}[UserControlDriverIdentify]");
                    code.Add($"{Indent}{Indent}public static {driverClassName} {funcName}(this {rootDriver} window)");
                    code.Add($"{Indent}{Indent}{Indent}=> window.Core.VisualTree().ByType(\"{targetControl.GetType().FullName}\").Single().Dynamic();");
                }
                code.Add($"{Indent}}}");
            }
            else if (targetControl is Window)
            {
                code.Add(string.Empty);
                code.Add($"{Indent}public static class {driverClassName}_Extensions");
                code.Add($"{Indent}{{");
                code.Add($"{Indent}{Indent}[WindowDriverIdentify(TypeFullName = \"{targetControl.GetType().FullName}\")]");
                code.Add($"{Indent}{Indent}public static {driverClassName} {GetFuncName(driverClassName)}(this WindowsAppFriend app)");
                code.Add($"{Indent}{Indent}{Indent}=> new {driverClassName}(app.WaitForIdentifyFromTypeFullName(\"{targetControl.GetType().FullName}\"));");
                code.Add($"{Indent}}}");
            }
            code.Add("}");
            return(string.Join(Environment.NewLine, code.ToArray()));
        }
示例#7
0
        private DriverInfo <DependencyObject> CreateDriverInfo(DependencyObject targetControl, string fileName)
        {
            var driverInfo = new DriverInfo <DependencyObject>(targetControl);

            var mappedControls = new List <DependencyObject>();
            var names          = new List <string>();
            var ancesters      = WPFUtility.GetVisualTreeAncestor(targetControl);

            var controlAndDefines = new List <ControlAndDefine>();

            //フィールドから検索
            foreach (var e in GetFields(targetControl))
            {
                //たまに親を持っているのがいるのではじく
                if (CollectionUtility.HasReference(ancesters, e.Control))
                {
                    continue;
                }

                //不正なフィールド名のものは取得できない
                if (!_dom.IsValidIdentifier(e.Name))
                {
                    continue;
                }

                //すでにマップされているかチェック
                if (CollectionUtility.HasReference(mappedControls, e.Control))
                {
                    continue;
                }

                //コントロールドライバ
                var driver = DriverCreatorUtils.GetDriverTypeFullName(e.Control, DriverCreatorAdapter.TypeFullNameAndControlDriver, DriverCreatorAdapter.TypeFullNameAndUserControlDriver);
                if (!string.IsNullOrEmpty(driver))
                {
                    mappedControls.Add(e.Control);
                    var name      = _customNameGenerator.MakeDriverPropName(e.Control, e.Name, names);
                    var typeName  = DriverCreatorUtils.GetTypeName(driver);
                    var nameSpace = DriverCreatorUtils.GetTypeNamespace(driver);
                    var key       = $"Core.Dynamic().{e.Name}";
                    controlAndDefines.Add(new ControlAndDefine(e.Control, name, $"public {typeName} {name} => {key};"));
                    DriverCreatorAdapter.AddCodeLineSelectInfo(fileName, key, e.Control);
                    if (!driverInfo.Usings.Contains(nameSpace))
                    {
                        driverInfo.Usings.Add(nameSpace);
                    }
                }
                //ユーザーコントロールドライバ
                else if (((e.Control is UserControl) && (e.Control.GetType() != typeof(UserControl))) ||
                         ((e.Control is Page) && (e.Control.GetType() != typeof(Page))))
                {
                    mappedControls.Add(e.Control);
                    var name     = _customNameGenerator.MakeDriverPropName(e.Control, e.Name, names);
                    var typeName = _driverTypeNameManager.MakeDriverType(e.Control, out var nameSpace);
                    var key      = $"Core.Dynamic().{e.Name}";
                    controlAndDefines.Add(new ControlAndDefine(e.Control, name, $"public {typeName} {name} => {key};"));
                    if (!string.IsNullOrEmpty(nameSpace) && (nameSpace != DriverCreatorAdapter.SelectedNamespace) && !driverInfo.Usings.Contains(nameSpace))
                    {
                        driverInfo.Usings.Add(nameSpace);
                    }
                    DriverCreatorAdapter.AddCodeLineSelectInfo(fileName, key, e.Control);
                }
            }

            //フィールド上に現れないオブジェクトを検索
            CreateDriverInfoFindFromControlTree(targetControl, driverInfo, controlAndDefines, mappedControls, names, fileName);

            //Sortのロジックがイマイチわかっていない。念のため
            try
            {
                // LogicalTree順のコントロールリスト取得
                var controlList = WPFUtility.GetLogicalTreeDescendants(targetControl, true, true, 0);

                // フィールドをタブオーダーでソート
                controlAndDefines.Sort((l, r) => controlList.IndexOf(l.Control) - controlList.IndexOf(r.Control));
            }
            catch { }

            //コンテキストメニュー特別処理
            foreach (var e in controlAndDefines)
            {
                driverInfo.Members.Add(e.Define);
                var frameworkElement = e.Control as FrameworkElement;
                if (frameworkElement != null && frameworkElement.ContextMenu != null)
                {
                    var core = (frameworkElement is Window || frameworkElement is UserControl || frameworkElement is Page) ?
                               ".Core" : string.Empty;
                    var code = $"public WPFContextMenu {e.Name}ContextMenu => new WPFContextMenu{{Target = {e.Name}{core}.AppVar}};";
                    driverInfo.Members.Add(code);
                }
            }

            return(driverInfo);
        }
        DriverIdentifyInfo[] GetIdentifyingCandidatesCore(CodeDomProvider dom, DependencyObject rootCtrl, DependencyObject elementCtrl)
        {
            if (rootCtrl == elementCtrl)
            {
                return(new DriverIdentifyInfo[0]);
            }

            var ancestor = new List <DependencyObject>();
            var current  = VisualTreeHelper.GetParent(elementCtrl);

            while (current != null)
            {
                if (CanBeParent(current))
                {
                    ancestor.Add(current);
                }
                if (ReferenceEquals(current, rootCtrl))
                {
                    break;
                }
                current = VisualTreeHelper.GetParent(current);
            }
            if (ancestor.Count == 0)
            {
                ancestor.Add(rootCtrl);
            }

            //Fieldでたどることができる範囲を取得
            var target = elementCtrl;
            var bindingExpressionCache = new BindingExpressionCache();
            var isPerfect   = true;
            var nameSource  = string.Empty;
            var usings      = new List <string>();
            var accessPaths = new List <string>();
            var isTree      = new List <bool>();

            foreach (var e in ancestor)
            {
                //直接のフィールドに持っているか?
                var path = GetAccessPath(e, target, dom);
                if (!string.IsNullOrEmpty(path))
                {
                    //最初がフィールドで特定できた場合はその名前を使う
                    if (target == elementCtrl)
                    {
                        var sp = path.Split('.');
                        nameSource = sp.Length == 0 ? string.Empty : sp[sp.Length - 1];
                    }

                    accessPaths.Insert(0, path);
                    isTree.Insert(0, false);
                    target = e;
                }
                else
                {
                    //Treeから検索
                    var logicalForGetter = WPFUtility.GetLogicalTreeDescendants(e, false, false, 0);
                    var visualForGetter  = WPFUtility.GetVisualTreeDescendants(e, false, false, 0);
                    path = MakeCodeGetFromTree(string.Empty, logicalForGetter, visualForGetter, target, bindingExpressionCache, usings, out var nogood, out var nameFromTree);
                    if (string.IsNullOrEmpty(path))
                    {
                        return(null);
                    }
                    if (nogood)
                    {
                        isPerfect = false;
                    }
                    accessPaths.Insert(0, path);
                    isTree.Insert(0, true);
                    target = e;
                    if (string.IsNullOrEmpty(nameSource))
                    {
                        nameSource = nameFromTree;
                    }
                }
            }

            if (target != rootCtrl)
            {
                return(null);
            }

            var names = new List <string>();
            var customNameGenerator = new DriverElementNameGeneratorAdaptor(dom);
            var name = customNameGenerator.MakeDriverPropName(elementCtrl, nameSource, names);

            var  appVarCast  = string.Empty;
            bool modeDynamic = false;

            for (int i = 0; i < isTree.Count; i++)
            {
                if (isTree[i])
                {
                    if (modeDynamic)
                    {
                        if (0 < i)
                        {
                            appVarCast         = "((AppVar)" + appVarCast;
                            accessPaths[i - 1] = accessPaths[i - 1] + ")";
                        }
                    }
                    modeDynamic = false;
                }
                else
                {
                    if (!modeDynamic)
                    {
                        accessPaths[i] = "Dynamic()." + accessPaths[i];
                    }
                    modeDynamic = true;
                }
            }
            var accessPath = string.Join(".", accessPaths.ToArray());

            if (!modeDynamic)
            {
                accessPath += ".Dynamic()";
            }

            return(new[]
            {
                new DriverIdentifyInfo
                {
                    IsPerfect = isPerfect,
                    Identify = appVarCast + "Core." + accessPath,
                    DefaultName = name,
                    ExtensionUsingNamespaces = usings.ToArray(),
                    DriverTypeCandidates = GetDriverTypeCandidates(elementCtrl)
                }
            });
        }