~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Core.UI/Helpers/VisualHelper.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
#region Usings
 
5
 
 
6
using System;
 
7
using System.Collections.Generic;
 
8
using System.Text;
 
9
using System.Threading;
 
10
using System.Windows;
 
11
using System.Windows.Controls;
 
12
using System.Windows.Controls.Primitives;
 
13
using System.Windows.Media;
 
14
using System.Windows.Threading;
 
15
using System.Windows.Input;
 
16
 
 
17
#endregion
 
18
 
 
19
namespace ICSharpCode.Data.Core.UI
 
20
{
 
21
        /// <summary>
 
22
        /// Helperklasse, um das Navigieren durch Visual-Trees, suchen von Resourcen in den Visuals und etc... zu erleichtern
 
23
        /// </summary>
 
24
        public class VisualHelper
 
25
        {               
 
26
                /// <summary>
 
27
                /// Rekursiv durch den Baum des DependencyObjects durchgehen
 
28
                /// </summary>
 
29
                /// <param name="visual"></param>
 
30
                /// <returns></returns>
 
31
                public static IEnumerable<DependencyObject> GetAllVisualChildren(DependencyObject visual)
 
32
                {
 
33
                        int childrenCount = VisualTreeHelper.GetChildrenCount(visual);
 
34
                        for (int i = 0; i < childrenCount; i++)
 
35
                        {
 
36
                                // das Child retournieren 
 
37
                                DependencyObject child = VisualTreeHelper.GetChild(visual, i);
 
38
                                yield return child;
 
39
 
 
40
                                // Rekursiv hinunter
 
41
                                if (VisualTreeHelper.GetChildrenCount(child) > 0)
 
42
                                        foreach (DependencyObject grandChild in GetAllVisualChildren(child))
 
43
                                                yield return grandChild;
 
44
                        }
 
45
                }
 
46
 
 
47
                /// <summary>
 
48
                /// liefert das FrameworkElement mit angegebenen Namen
 
49
                /// </summary>
 
50
                /// <param name="visualParent"></param>
 
51
                /// <param name="name"></param>
 
52
                /// <returns></returns>
 
53
                public static FrameworkElement GetChild(DependencyObject visualParent, string name)
 
54
                {
 
55
 
 
56
                        // Animation zum Anzeigen der neuen Grid starten
 
57
                        foreach (DependencyObject child in VisualHelper.GetAllVisualChildren(visualParent))
 
58
                        {
 
59
                                FrameworkElement childElement = child as FrameworkElement;
 
60
 
 
61
                                if (childElement != null && childElement.Name != string.Empty)
 
62
                                        System.Diagnostics.Debug.WriteLine(string.Format("VisualHelper.GetChild: such nach [{0}] child = {1}", name, childElement.Name));
 
63
 
 
64
                                if (childElement != null && childElement.Name == name)
 
65
                                {
 
66
                                        return childElement;
 
67
                                }
 
68
                        }
 
69
                        return null;
 
70
                }
 
71
 
 
72
                /// <summary>
 
73
                /// sucht ein SubElement eines 'templated' FrameworkElements
 
74
                /// </summary>
 
75
                /// <param name="subElementName"></param>
 
76
                /// <param name="control"></param>
 
77
                /// <returns></returns>
 
78
                public static ElementType TryFindSubElement<ElementType>(string subElementName, Control control) where ElementType : class
 
79
                {
 
80
                        if (control == null || control.Template == null)
 
81
                                return null;
 
82
 
 
83
                        // sucht das Element
 
84
                        object subObject = control.Template.FindName(subElementName, control);
 
85
                        if (subObject == null)
 
86
                                return null;
 
87
 
 
88
                        ElementType subElement = subObject as ElementType;
 
89
                        if (subElement == null)
 
90
                                return null;
 
91
 
 
92
                        return subElement;
 
93
                }
 
94
 
 
95
                /// <summary>
 
96
                /// sucht ein SubElement eines 'templated' FrameworkElements
 
97
                /// </summary>
 
98
                /// <param name="subElementName"></param>
 
99
                /// <param name="control"></param>
 
100
                /// <returns></returns>
 
101
                public static ElementType FindSubElement<ElementType>(string subElementName, Control control) where ElementType : class
 
102
                {
 
103
                        if (control == null || control.Template == null)
 
104
                        {
 
105
                                throw new Exception("Element hat kein Template!");
 
106
                        }
 
107
 
 
108
                        // sucht das Element
 
109
                        object subObject = control.Template.FindName(subElementName, control);
 
110
                        if (subObject == null)
 
111
                        {
 
112
                                throw new Exception("Template-Subelement nicht gefunden!");
 
113
                        }
 
114
 
 
115
                        ElementType subElement = subObject as ElementType;
 
116
                        if (subElement == null)
 
117
                        {
 
118
                                throw new Exception("Template-Subelement nicht gefunden!");
 
119
                        }
 
120
 
 
121
                        return subElement;
 
122
                }
 
123
 
 
124
                /// <summary>
 
125
                /// Sucht die Resource in dem FrameworkElement (dem 'hierarchischen Baum') aufwärts
 
126
                /// </summary>
 
127
                /// <typeparam name="T"></typeparam>
 
128
                /// <param name="key"></param>
 
129
                /// <param name="element"></param>
 
130
                /// <returns></returns>
 
131
                public static T FindResource<T>(string key, FrameworkElement element)
 
132
                {
 
133
                        try
 
134
                        {
 
135
                                T value = (T)element.FindResource(key);
 
136
                                return value;
 
137
                        }
 
138
                        catch (ResourceReferenceKeyNotFoundException)
 
139
                        {
 
140
                                throw new Exception("Control hat kein Template!");
 
141
                        }
 
142
                }
 
143
 
 
144
                /// <summary>
 
145
                /// Sucht die Resource in dem FrameworkElement (dem 'hierarchischen Baum') aufwärts, 
 
146
                /// falls nicht gefunden, wird der Defaultwerte zurückgegeben
 
147
                /// </summary>
 
148
                /// <typeparam name="T"></typeparam>
 
149
                /// <param name="key"></param>
 
150
                /// <param name="element"></param>
 
151
                /// <param name="defaultValue"></param>
 
152
                /// <returns></returns>
 
153
                public static T FindResource<T>(string key, FrameworkElement element, T defaultValue)
 
154
                {
 
155
                        try
 
156
                        {
 
157
                                return (T)element.FindResource(key);
 
158
                        }
 
159
                        catch (ResourceReferenceKeyNotFoundException)
 
160
                        {
 
161
                                return defaultValue;
 
162
                        }
 
163
                        catch (Exception)
 
164
                        {
 
165
                                throw new Exception("Control hat kein Template!");
 
166
                        }
 
167
                }
 
168
 
 
169
                /// <summary>
 
170
                /// Sucht das Element unter der Mouse mit dem Namen name
 
171
                /// </summary>
 
172
                /// <param name="reference"></param>
 
173
                /// <param name="mousePosition"></param>
 
174
                /// <param name="key"></param>
 
175
                /// <returns></returns>
 
176
                public static FrameworkElement FindElementUnderPointer(Visual reference, Point mousePosition, string name)
 
177
                {
 
178
                        // Hit-test to find out the ItemsControl under the mouse-pointer.
 
179
                        _element = null;
 
180
                        _hittedElements = null;
 
181
                        _name = name;
 
182
                        VisualTreeHelper.HitTest(reference,
 
183
                                new HitTestFilterCallback(VisualHelper.FilterHitTestKeyCallback),
 
184
                                new HitTestResultCallback(VisualHelper.HitTestResultCallback),
 
185
                                new PointHitTestParameters(mousePosition));
 
186
 
 
187
                        try
 
188
                        {
 
189
                                return _element;
 
190
                        }
 
191
                        finally
 
192
                        {
 
193
                                _element = null;
 
194
                                _hittedElements = null;
 
195
                                _name = null;
 
196
                                _type = null;
 
197
                        }
 
198
                }
 
199
 
 
200
                /// <summary>
 
201
                /// Sucht das Element unter der Mouse des Typs type
 
202
                /// </summary>
 
203
                /// <param name="reference"></param>
 
204
                /// <param name="mousePosition"></param>
 
205
                /// <param name="type"></param>
 
206
                /// <returns></returns>
 
207
                public static FrameworkElement FindElementUnderPointer(Visual reference, Point mousePosition, Type type)
 
208
                {
 
209
                        // Hit-test to find out the ItemsControl under the mouse-pointer.
 
210
                        _element = null;
 
211
                        _hittedElements = null;
 
212
                        _type = type;
 
213
                        VisualTreeHelper.HitTest(reference,
 
214
                                new HitTestFilterCallback(VisualHelper.FilterHitTestTypeCallback),
 
215
                                new HitTestResultCallback(VisualHelper.HitTestResultCallback),
 
216
                                new PointHitTestParameters(mousePosition));
 
217
 
 
218
                        try
 
219
                        {
 
220
                                return _element;
 
221
                        }
 
222
                        finally
 
223
                        {
 
224
                                _element = null;
 
225
                                _name = null;
 
226
                                _hittedElements = null;
 
227
                                _type = null;
 
228
                        }
 
229
                }
 
230
 
 
231
                public static IEnumerable<FrameworkElement> GetElementsUnderPointer(Visual reference, Point mousePosition)
 
232
                {
 
233
                        // Hit-test to find out the ItemsControl under the mouse-pointer.
 
234
                        _element = null;
 
235
                        _hittedElements = new List<FrameworkElement>();
 
236
                        _type = null;
 
237
 
 
238
                        VisualTreeHelper.HitTest(reference,
 
239
                                new HitTestFilterCallback(VisualHelper.NoFilterHitTestCallback),
 
240
                                new HitTestResultCallback(VisualHelper.HitTestResultCallback),
 
241
                                new PointHitTestParameters(mousePosition));
 
242
 
 
243
                        try
 
244
                        {
 
245
                                return _hittedElements;
 
246
                        }
 
247
                        finally
 
248
                        {
 
249
                                _element = null;
 
250
                                _hittedElements = null;
 
251
                                _name = null;
 
252
                                _type = null;
 
253
                        }
 
254
                }
 
255
 
 
256
                private static FrameworkElement _element = null;
 
257
                private static List<FrameworkElement> _hittedElements = null;
 
258
                private static string _name = null;
 
259
                private static Type _type = null;
 
260
 
 
261
                private static HitTestFilterBehavior FilterHitTestKeyCallback(DependencyObject target)
 
262
                {
 
263
                        FrameworkElement element = target as FrameworkElement;
 
264
                        if (element != null && element.Name == _name)
 
265
                        {
 
266
                                if (_hittedElements != null)
 
267
                                        _hittedElements.Add(element);
 
268
                                _element = element;
 
269
                                return HitTestFilterBehavior.Stop;
 
270
                        }
 
271
                        else
 
272
                        {
 
273
                                if (_hittedElements != null)
 
274
                                        _hittedElements.Add(element);
 
275
                                return HitTestFilterBehavior.Continue;
 
276
                        }
 
277
                }
 
278
 
 
279
                private static HitTestFilterBehavior FilterHitTestTypeCallback(DependencyObject target)
 
280
                {
 
281
                        if (target.GetType().IsAssignableFrom(_type))
 
282
                        {
 
283
                                _element = target as FrameworkElement;
 
284
                                if (_hittedElements != null)
 
285
                                        _hittedElements.Add(_element);
 
286
                                return HitTestFilterBehavior.Stop;
 
287
                        }
 
288
                        else
 
289
                        {
 
290
                                if (_hittedElements != null)
 
291
                                        _hittedElements.Add(target as FrameworkElement);
 
292
                                return HitTestFilterBehavior.Continue;
 
293
                        }
 
294
                }
 
295
 
 
296
                private static HitTestFilterBehavior NoFilterHitTestCallback(DependencyObject target)
 
297
                {
 
298
                        if (_hittedElements != null && target is FrameworkElement && (target as FrameworkElement).IsVisible)
 
299
                                _hittedElements.Add(target as FrameworkElement);
 
300
                        return HitTestFilterBehavior.Continue;
 
301
                }
 
302
 
 
303
                private static HitTestResultBehavior HitTestResultCallback(HitTestResult result)
 
304
                {
 
305
                        return HitTestResultBehavior.Continue;
 
306
                }
 
307
 
 
308
                /// <summary>
 
309
                /// Gibt ein visuelles Child eines bestimmten Typs eines DependencyObjects zurück.
 
310
                /// </summary>
 
311
                /// <typeparam name="TChild"></typeparam>
 
312
                /// <param name="obj"></param>
 
313
                /// <returns></returns>
 
314
                public static TChild GetVisualChild<TChild>(DependencyObject obj) where TChild : DependencyObject
 
315
                {
 
316
                        if (obj == null)
 
317
                                return null;
 
318
 
 
319
                        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
 
320
                        {
 
321
                                // TODO: Was passiert hier, wenn ich kein Visual, sondern z.B. ein Run will?
 
322
                                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
 
323
                                if (child != null && child is TChild)
 
324
                                        return (TChild)child;
 
325
                                else
 
326
                                {
 
327
                                        TChild childOfChild = GetVisualChild<TChild>(child);
 
328
                                        if (childOfChild != null)
 
329
                                                return childOfChild;
 
330
                                }
 
331
                        }
 
332
                        return null;
 
333
                }
 
334
 
 
335
                /// <summary>
 
336
                /// Gibt ein visuelles Child mit einem bestimmten Namen eines DependencyObjects zurück.
 
337
                /// </summary>
 
338
                /// <typeparam name="TChild"></typeparam>
 
339
                /// <param name="obj"></param>
 
340
                /// <param name="name"></param>
 
341
                /// <returns></returns>
 
342
                public static TChild GetVisualChild<TChild>(DependencyObject obj, string name) where TChild : FrameworkElement
 
343
                {
 
344
                        if (obj == null)
 
345
                                return null;
 
346
 
 
347
                        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
 
348
                        {
 
349
                                // TODO: Was passiert hier, wenn ich kein Visual, sondern z.B. ein Run will?
 
350
                                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
 
351
                                if (child != null && child is TChild && ((TChild)child).Name == name)
 
352
                                        return (TChild)child;
 
353
                                else
 
354
                                {
 
355
                                        TChild childOfChild = GetVisualChild<TChild>(child, name);
 
356
                                        if (childOfChild != null)
 
357
                                                return childOfChild;
 
358
                                }
 
359
                        }
 
360
                        return null;
 
361
                }
 
362
 
 
363
                /// <summary>
 
364
                /// Gibt ein visuelles Child mit einem bestimmten Namen eines DependencyObjects zurück.
 
365
                /// </summary>
 
366
                /// <param name="obj"></param>
 
367
                /// <param name="name"></param>
 
368
                /// <returns></returns>
 
369
                /// <remarks>Ich habe diese Methode hier aus Rückwärtskompatibilitätsgründen zurückgelassen.</remarks>
 
370
                public static FrameworkElement GetVisualChild(DependencyObject obj, string name)
 
371
                {
 
372
                        return GetVisualChild<FrameworkElement>(obj, name);
 
373
                }
 
374
 
 
375
                /// <summary>
 
376
                /// Gibt ein visuelles Child, welches eine übergebene Bedingung erfüllt zurück
 
377
                /// </summary>
 
378
                /// <typeparam name="TChild"></typeparam>
 
379
                /// <param name="obj"></param>
 
380
                /// <param name="comparePredicate"></param>
 
381
                /// <returns></returns>
 
382
                public static TChild GetVisualChild<TChild>(DependencyObject obj, Func<DependencyObject, bool> comparePredicate) where TChild : FrameworkElement
 
383
                {
 
384
                        if (obj == null)
 
385
                                return null;
 
386
 
 
387
                        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
 
388
                        {
 
389
                                // TODO: Was passiert hier, wenn ich kein Visual, sondern z.B. ein Run will?
 
390
                                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
 
391
                                if (child != null && child is TChild && child is DependencyObject && comparePredicate(child as DependencyObject))
 
392
                                        return (TChild)child;
 
393
                                else
 
394
                                {
 
395
                                        TChild childOfChild = GetVisualChild<TChild>(child, comparePredicate);
 
396
                                        if (childOfChild != null)
 
397
                                                return childOfChild;
 
398
                                }
 
399
                        }
 
400
                        return null;
 
401
                }
 
402
 
 
403
                /// <summary>
 
404
                /// Gibt ein visuelles Child, welches eine übergebene Bedingung erfüllt zurück
 
405
                /// </summary>
 
406
                /// <param name="obj"></param>
 
407
                /// <param name="name"></param>
 
408
                /// <returns></returns>
 
409
                /// <remarks>Ich habe diese Methode hier aus Rückwärtskompatibilitätsgründen zurückgelassen.</remarks>
 
410
                public static FrameworkElement GetVisualChild(DependencyObject obj, Func<DependencyObject, bool> comparePredicate)
 
411
                {
 
412
                        return GetVisualChild<FrameworkElement>(obj, comparePredicate);
 
413
                }
 
414
 
 
415
                /// <summary>
 
416
                /// Gibt einen visuellen Parent eines bestimmten Typs eines DependencyObjects zurück.
 
417
                /// </summary>
 
418
                /// <typeparam name="TParent"></typeparam>
 
419
                /// <param name="obj"></param>
 
420
                /// <returns></returns>
 
421
                public static TParent GetVisualParent<TParent>(DependencyObject obj) where TParent : DependencyObject
 
422
                {
 
423
                        return GetVisualParent<TParent>(obj, true);
 
424
                }
 
425
 
 
426
                /// <summary>
 
427
                /// Gibt einen visuellen Parent mit einem speziellen Namen eines DependencyObjects zurück.
 
428
                /// </summary>
 
429
                /// <typeparam name="TParent"></typeparam>
 
430
                /// <param name="obj"></param>
 
431
                /// <param name="parentName"></param>
 
432
                /// <returns></returns>
 
433
                public static FrameworkElement GetVisualParent(DependencyObject obj, string parentName)
 
434
                {
 
435
                        return GetVisualParent<FrameworkElement>(obj, true, parent => ((FrameworkElement)parent).Name == parentName);
 
436
                }
 
437
 
 
438
                /// <summary>
 
439
                /// Gibt einen visuellen Parent eines bestimmten Typs eines DependencyObjects zurück.
 
440
                /// </summary>
 
441
                /// <typeparam name="TParent"></typeparam>
 
442
                /// <param name="obj"></param>
 
443
                /// <param name="walkThroughPopupRoot">Gibt an, ob auch über einen PopupRoot weitergemacht werden soll.</param>
 
444
                /// <returns></returns>
 
445
                public static TParent GetVisualParent<TParent>(DependencyObject obj, bool walkThroughPopupRoot) where TParent : DependencyObject
 
446
                {
 
447
                        if (obj == null)
 
448
                                return null;
 
449
 
 
450
                        return GetVisualParent<TParent>(obj, walkThroughPopupRoot,
 
451
                                parent => parent != null && parent is TParent);
 
452
                }
 
453
 
 
454
                /// <summary>
 
455
                /// Gibt einen visuellen Parent eines bestimmten Typs eines DependencyObjects zurück.
 
456
                /// </summary>
 
457
                /// <typeparam name="TParent"></typeparam>
 
458
                /// <param name="obj"></param>
 
459
                /// <param name="walkThroughPopupRoot">Gibt an, ob auch über einen PopupRoot weitergemacht werden soll.</param>
 
460
                /// <param name="comparePredicate">Func mit dem Parent-Vergleich</param>
 
461
                /// <returns></returns>
 
462
                public static TParent GetVisualParent<TParent>(DependencyObject obj, bool walkThroughPopupRoot,
 
463
                        Func<DependencyObject, bool> comparePredicate)
 
464
                                where TParent : DependencyObject
 
465
                {
 
466
                        if (obj == null)
 
467
                                return null;
 
468
 
 
469
                        // Wenn es kein Visual (z.B. Run) oder ein PopupRoot ist, dann komme ich nur im LogicalTree weiter voran...
 
470
                        DependencyObject parent = (!(obj is Visual) || (walkThroughPopupRoot && obj.GetType().Name == "PopupRoot")) ?
 
471
                                LogicalTreeHelper.GetParent(obj) : VisualTreeHelper.GetParent(obj);
 
472
                        if (comparePredicate(parent))
 
473
                                return (TParent)parent;
 
474
                        else
 
475
                                return GetVisualParent<TParent>(parent, walkThroughPopupRoot, comparePredicate);
 
476
                }
 
477
 
 
478
                public static object GetVisualParentObject(DependencyObject obj, bool walkThroughPopupRoot,
 
479
                        Func<DependencyObject, bool> comparePredicate)
 
480
                {
 
481
                        if (obj == null)
 
482
                                return null;
 
483
 
 
484
                        // Wenn es kein Visual (z.B. Run) oder ein PopupRoot ist, dann komme ich nur im LogicalTree weiter voran...
 
485
                        DependencyObject parent = (!(obj is Visual) || (walkThroughPopupRoot && obj.GetType().Name == "PopupRoot")) ?
 
486
                                LogicalTreeHelper.GetParent(obj) : VisualTreeHelper.GetParent(obj);
 
487
                        if (comparePredicate(parent))
 
488
                                return parent;
 
489
                        else
 
490
                                return GetVisualParentObject(parent, walkThroughPopupRoot, comparePredicate);
 
491
                }
 
492
 
 
493
        /// <summary>
 
494
        /// Runs an Action in the current dispatcher.
 
495
        /// </summary>
 
496
        /// <param name="actionToRun"></param>
 
497
        public static void RunInDispatcher(Action actionToRun)
 
498
        {
 
499
            if (Application.Current != null)
 
500
                RunInDispatcher(Application.Current.Dispatcher, actionToRun);
 
501
        }
 
502
 
 
503
        /// <summary>
 
504
        /// Runs an Action in a given dispatcher.
 
505
        /// </summary>
 
506
        /// <param name="dispatcher"></param>
 
507
        /// <param name="actionToRun"></param>
 
508
        public static void RunInDispatcher(Dispatcher dispatcher, Action actionToRun)
 
509
        {
 
510
            dispatcher.Invoke(DispatcherPriority.Background, actionToRun);
 
511
        }
 
512
 
 
513
                /// <summary>
 
514
                /// Runs through all items in the dispatcher.
 
515
                /// </summary>
 
516
                public static void DoEvents()
 
517
                {
 
518
                        if (Application.Current != null)
 
519
                                DoEvents(Application.Current.Dispatcher);
 
520
                }
 
521
 
 
522
                /// <summary>
 
523
                /// Gives DispatcherFrames of the given Dispatcher priority, if
 
524
                /// their DispatcherPriority is higher than "DispatcherPriority.Background".
 
525
                /// </summary>
 
526
                /// <param name="dispatcherToPause"></param>
 
527
                public static void DoEvents(Dispatcher dispatcherToPause)
 
528
                {
 
529
                        dispatcherToPause.Invoke(DispatcherPriority.Background, new System.Action(() => { }));
 
530
                }
 
531
        }
 
532
}