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); } } } } }
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); }
internal string MakeCodeGetFromTree(string prefix, List <DependencyObject> logical, List <DependencyObject> visual, DependencyObject obj, BindingExpressionCache cache, List <string> usings, out bool nogood) { nogood = false; var preIdentify = prefix + "LogicalTree()"; foreach (var tree in new[] { logical, visual }) { if (Exist(tree, obj)) { //バインディングで特定できた var identifyCode = TryIdentifyFromBinding(tree, obj, cache); if (!string.IsNullOrEmpty(identifyCode)) { return($"{preIdentify}{identifyCode}.Single().Dynamic()"); } var sameType = CollectionUtility.OfType(tree, obj.GetType()); preIdentify = $"{preIdentify}.ByType(\"{obj.GetType().FullName}\")"; //タイプとバインディングで特定できた identifyCode = TryIdentifyFromBinding(sameType, obj, cache); if (!string.IsNullOrEmpty(identifyCode)) { return($"{preIdentify}{identifyCode}.Single().Dynamic()"); } if (sameType.Count == 1) { //タイプで特定できた return($"{preIdentify}.Single().Dynamic()"); } //特殊な手法で特定できた var code = _customIdentify.Generate(obj, tree, usings); if (!string.IsNullOrEmpty(code)) { return(preIdentify + code); } } preIdentify = prefix + "VisualTree()"; } nogood = true; //特定できなかったのでインデックスで行く preIdentify = prefix + "LogicalTree()"; foreach (var tree in new[] { logical, visual }) { if (Exist(tree, obj)) { var sameType = CollectionUtility.OfType(tree, obj.GetType()); preIdentify = $"{preIdentify}.ByType(\"{obj.GetType().FullName}\")"; for (int i = 0; i < sameType.Count; i++) { if (ReferenceEquals(sameType[i], obj)) { return($"{preIdentify}[{i}].Dynamic()"); } } } preIdentify = prefix + "VisualTree()"; } return(string.Empty); }
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) } }); }