5 // Moonlight List (moonlight-list@lists.ximian.com)
7 // Copyright 2008 Novell, Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Reflection
;
31 using System
.Collections
.Generic
;
32 using System
.Windows
.Controls
;
33 using System
.Windows
.Data
;
34 using System
.Windows
.Input
;
35 using System
.Windows
.Markup
;
36 using System
.Windows
.Media
;
37 using System
.Windows
.Automation
;
39 namespace System
.Windows
{
40 public abstract partial class FrameworkElement
: UIElement
{
42 static FrameworkElement ()
44 StyleProperty
.Validate
= delegate (DependencyObject target
, DependencyProperty propety
, object value) {
45 Type styleType
= ((Style
)value).TargetType
;
46 if (!styleType
.IsAssignableFrom (target
.GetType ()))
47 throw new System
.Windows
.Markup
.XamlParseException (string.Format ("Target is of type {0} but the Style requires {1}", target
.GetType ().Name
, styleType
.Name
));
50 DataContextProperty
.AddPropertyChangeCallback (DataContextChanged
);
53 static void DataContextChanged (DependencyObject sender
, DependencyPropertyChangedEventArgs args
)
55 (sender
as FrameworkElement
).OnDataContextChanged (args
.OldValue
, args
.NewValue
);
58 void OnDataContextChanged (object oldValue
, object newValue
)
60 InvalidateLocalBindings ();
61 InvalidateSubtreeBindings ();
64 void InvalidateSubtreeBindings ()
66 for (int c
= 0; c
< VisualTreeHelper
.GetChildrenCount (this); c
++) {
67 FrameworkElement obj
= VisualTreeHelper
.GetChild (this, c
) as FrameworkElement
;
70 obj
.InvalidateLocalBindings ();
71 obj
.InvalidateSubtreeBindings ();
75 bool invalidatingLocalBindings
;
77 void InvalidateLocalBindings ()
79 if (expressions
.Count
== 0)
82 if (invalidatingLocalBindings
)
85 invalidatingLocalBindings
= true;
87 Dictionary
<DependencyProperty
, Expression
> old
= expressions
;
88 expressions
= new Dictionary
<DependencyProperty
, Expression
> ();
89 foreach (var keypair
in old
) {
90 if (keypair
.Value
is BindingExpressionBase
) {
91 BindingExpressionBase beb
= (BindingExpressionBase
)keypair
.Value
;
93 SetValue (keypair
.Key
, beb
);
95 else if (keypair
.Value
is TemplateBindingExpression
) {
96 // we don't invalidate
98 // expressions, so just add it
99 // back to the expressions
101 expressions
.Add (keypair
.Key
, keypair
.Value
);
105 invalidatingLocalBindings
= false;
108 public event EventHandler LayoutUpdated
{
109 add { Deployment.Current.LayoutUpdated += value; }
110 remove { Deployment.Current.LayoutUpdated -= value; }
115 * XXX these are marked internal because making them private seems
116 * to cause the GC to collect them
118 internal MeasureOverrideCallback measure_cb
;
119 internal ArrangeOverrideCallback arrange_cb
;
120 internal GetDefaultTemplateCallback get_default_template_cb
;
121 internal LoadedCallback loaded_hook_cb
;
123 Dictionary
<DependencyProperty
, Expression
> expressions
= new Dictionary
<DependencyProperty
, Expression
> ();
125 private static bool UseNativeLayoutMethod (Type type
)
127 return type
== typeof (FrameworkElement
)
128 || type
== typeof (Canvas
)
129 || type
== typeof (Grid
);
132 bool OverridesGetDefaultTemplate ()
134 return this is ContentPresenter
135 || this is ItemsPresenter
136 || this is ItemsControl
137 || this is ContentControl
;
140 private bool OverridesLayoutMethod (string name
)
142 var method
= GetType ().GetMethod (name
, BindingFlags
.NonPublic
| BindingFlags
.Instance
| BindingFlags
.FlattenHierarchy
);
146 if (!method
.IsVirtual
|| !method
.IsFamily
)
149 if (method
.ReturnType
!= typeof (Size
))
152 if (UseNativeLayoutMethod (method
.DeclaringType
))
155 var parameters
= method
.GetParameters ();
156 if (parameters
.Length
!= 1 || parameters
[0].ParameterType
!= typeof (Size
))
162 private void Initialize ()
164 if (OverridesLayoutMethod ("MeasureOverride"))
165 measure_cb
= new MeasureOverrideCallback (InvokeMeasureOverride
);
166 if (OverridesLayoutMethod ("ArrangeOverride"))
167 arrange_cb
= new ArrangeOverrideCallback (InvokeArrangeOverride
);
168 if (OverridesGetDefaultTemplate ())
169 get_default_template_cb
= InvokeGetDefaultTemplate
;
170 loaded_hook_cb
= InvokeLoadedHook
;
171 NativeMethods
.framework_element_register_managed_overrides (native
, measure_cb
, arrange_cb
, get_default_template_cb
, loaded_hook_cb
);
174 public object FindName (string name
)
176 return DepObjectFindName (name
);
179 internal void SetTemplateBinding (DependencyProperty dp
, TemplateBindingExpression tb
)
181 tb
.AttachChangeHandler();
185 // Do nothing here - The DP should still have its default value
189 public BindingExpressionBase
SetBinding (DependencyProperty dp
, Binding binding
)
192 throw new ArgumentNullException ("dp");
194 throw new ArgumentNullException ("binding");
196 BindingExpression e
= new BindingExpression (binding
, this, dp
);
202 protected virtual Size
MeasureOverride (Size availableSize
)
204 return NativeMethods
.framework_element_measure_override (native
, availableSize
);
207 protected virtual Size
ArrangeOverride (Size finalSize
)
209 return NativeMethods
.framework_element_arrange_override (native
, finalSize
);
212 public DependencyObject Parent
{
214 return NativeDependencyObjectHelper
.FromIntPtr (NativeMethods
.framework_element_get_logical_parent (native
)) as DependencyObject
;
218 internal DependencyObject SubtreeObject
{
220 return NativeDependencyObjectHelper
.FromIntPtr (NativeMethods
.uielement_get_subtree_object (native
)) as DependencyObject
;
224 public event EventHandler
<ValidationErrorEventArgs
> BindingValidationError
;
226 internal virtual void InvokeOnApplyTemplate ()
231 internal virtual void InvokeLoaded ()
233 InvalidateLocalBindings ();
234 InvalidateSubtreeBindings ();
237 private Size
InvokeMeasureOverride (Size availableSize
)
240 return MeasureOverride (availableSize
);
241 } catch (Exception ex
) {
243 Console
.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeMeasureOverride: {0}", ex
);
251 private Size
InvokeArrangeOverride (Size finalSize
)
254 return ArrangeOverride (finalSize
);
255 } catch (Exception ex
) {
257 Console
.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeArrangeOverride: {0}", ex
);
265 static IntPtr
InvokeGetDefaultTemplate (IntPtr fwe_ptr
)
267 UIElement root
= null;
269 FrameworkElement element
= (FrameworkElement
) NativeDependencyObjectHelper
.FromIntPtr (fwe_ptr
);
270 root
= element
.GetDefaultTemplate ();
271 } catch (Exception ex
) {
273 Console
.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeGetDefaultTemplate: {0}", ex
);
278 return root
== null ? IntPtr
.Zero
: root
.native
;
281 static void InvokeLoadedHook (IntPtr fwe_ptr
)
284 FrameworkElement element
= (FrameworkElement
) NativeDependencyObjectHelper
.FromIntPtr (fwe_ptr
);
285 element
.InvokeLoaded ();
286 } catch (Exception ex
) {
288 Console
.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeLoaded: {0}", ex
);
295 internal virtual UIElement
GetDefaultTemplate ()
300 public virtual void OnApplyTemplate ()
302 // according to doc this is not fully implemented since SL templates applies
303 // to Control/ContentPresenter and is defined here for WPF compatibility
306 internal override void ClearValueImpl (DependencyProperty dp
)
308 RemoveExpression (dp
);
309 base.ClearValueImpl (dp
);
312 internal void RaiseBindingValidationError (ValidationErrorEventArgs e
)
314 EventHandler
<ValidationErrorEventArgs
> h
= BindingValidationError
;
319 void RemoveExpression (DependencyProperty dp
)
322 if (expressions
.TryGetValue (dp
, out e
)) {
323 expressions
.Remove (dp
);
328 internal override void SetValueImpl (DependencyProperty dp
, object value)
330 bool addingExpression
= false;
332 Expression expression
= value as Expression
;
333 BindingExpressionBase bindingExpression
= expression
as BindingExpressionBase
;
335 if (bindingExpression
!= null) {
336 if (string.IsNullOrEmpty (bindingExpression
.Binding
.Path
.Path
) &&
337 bindingExpression
.Binding
.Mode
== BindingMode
.TwoWay
)
338 throw new ArgumentException ("TwoWay bindings require a non-empty Path");
341 expressions
.TryGetValue (dp
, out existing
);
343 if (expression
!= null) {
344 if (existing
!= null)
345 RemoveExpression (dp
);
346 expressions
.Add (dp
, expression
);
348 addingExpression
= true;
349 value = expression
.GetValue (dp
);
350 } else if (existing
!= null) {
351 if (existing
is BindingExpressionBase
) {
352 BindingExpressionBase beb
= (BindingExpressionBase
)existing
;
354 if (beb
.Binding
.Mode
== BindingMode
.TwoWay
)
355 beb
.SetValue (value);
356 else if (!(beb
.UpdatingSource
&& beb
.Binding
.Mode
== BindingMode
.OneWay
)) {
357 RemoveExpression (dp
);
360 else if (existing
is TemplateBindingExpression
) {
361 TemplateBindingExpression tb
= (TemplateBindingExpression
)existing
;
363 if (!tb
.UpdatingTarget
)
364 RemoveExpression (dp
);
367 RemoveExpression (dp
);
372 base.SetValueImpl (dp
, value);
375 if (!addingExpression
)
378 base.SetValueImpl (dp
, dp
.DefaultValue
);
382 internal override object ReadLocalValueImpl (DependencyProperty dp
)
384 Expression expression
;
385 if (expressions
.TryGetValue (dp
, out expression
))
387 return base.ReadLocalValueImpl (dp
);
390 #region UIA Events and Methods
392 // All events are 1-1 to each attached property defined in:
393 // System.Windows.Automation.AutomationProperties
395 internal event DependencyPropertyChangedEventHandler AcceleratorKeyChanged
;
396 internal event DependencyPropertyChangedEventHandler AccessKeyChanged
;
397 internal event DependencyPropertyChangedEventHandler AutomationIdChanged
;
398 internal event DependencyPropertyChangedEventHandler HelpTextChanged
;
399 internal event DependencyPropertyChangedEventHandler IsRequiredForFormChanged
;
400 internal event DependencyPropertyChangedEventHandler ItemStatusChanged
;
401 internal event DependencyPropertyChangedEventHandler ItemTypeChanged
;
402 internal event DependencyPropertyChangedEventHandler LabeledByChanged
;
403 internal event DependencyPropertyChangedEventHandler NameChanged
;
405 internal void RaiseAcceleratorKeyChanged (DependencyPropertyChangedEventArgs args
)
407 if (AcceleratorKeyChanged
!= null)
408 AcceleratorKeyChanged (this, args
);
411 internal void RaiseAccessKeyChanged (DependencyPropertyChangedEventArgs args
)
413 if (AccessKeyChanged
!= null)
414 AccessKeyChanged (this, args
);
417 internal void RaiseAutomationIdChanged (DependencyPropertyChangedEventArgs args
)
419 if (AutomationIdChanged
!= null)
420 AutomationIdChanged (this, args
);
423 internal void RaiseHelpTextChanged (DependencyPropertyChangedEventArgs args
)
425 if (HelpTextChanged
!= null)
426 HelpTextChanged (this, args
);
429 internal void RaiseIsRequiredForFormChanged (DependencyPropertyChangedEventArgs args
)
431 if (IsRequiredForFormChanged
!= null)
432 IsRequiredForFormChanged (this, args
);
435 internal void RaiseItemStatusChanged (DependencyPropertyChangedEventArgs args
)
437 if (ItemStatusChanged
!= null)
438 ItemStatusChanged (this, args
);
441 internal void RaiseItemTypeChanged (DependencyPropertyChangedEventArgs args
)
443 if (ItemTypeChanged
!= null)
444 ItemTypeChanged (this, args
);
447 internal void RaiseLabeledByChanged (DependencyPropertyChangedEventArgs args
)
449 if (LabeledByChanged
!= null)
450 LabeledByChanged (this, args
);
453 internal void RaiseNameChanged (DependencyPropertyChangedEventArgs args
)
455 if (NameChanged
!= null)
456 NameChanged (this, args
);