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); } }
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); }
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); } } } } }
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())); }
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) } }); }