in class/Microsoft.SilverlightControls/:
[moon.git] / class / System.Windows / System.Windows / FrameworkElement.cs
blob3bad9bc62d049569f66b3fd34122f7b56d0dcfdb
1 //
2 // FrameworkElement.cs
3 //
4 // Contact:
5 // Moonlight List (moonlight-list@lists.ximian.com)
6 //
7 // Copyright 2008 Novell, Inc.
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
29 using Mono;
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;
68 if (obj == null)
69 continue;
70 obj.InvalidateLocalBindings ();
71 obj.InvalidateSubtreeBindings ();
75 bool invalidatingLocalBindings;
77 void InvalidateLocalBindings ()
79 if (expressions.Count == 0)
80 return;
82 if (invalidatingLocalBindings)
83 return;
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;
92 beb.Invalidate ();
93 SetValue (keypair.Key, beb);
95 else if (keypair.Value is TemplateBindingExpression) {
96 // we don't invalidate
97 // templatebinding
98 // expressions, so just add it
99 // back to the expressions
100 // list.
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);
143 if (method == null)
144 return false;
146 if (!method.IsVirtual || !method.IsFamily)
147 return false;
149 if (method.ReturnType != typeof (Size))
150 return false;
152 if (UseNativeLayoutMethod (method.DeclaringType))
153 return false;
155 var parameters = method.GetParameters ();
156 if (parameters.Length != 1 || parameters [0].ParameterType != typeof (Size))
157 return false;
159 return true;
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();
182 try {
183 SetValue (dp, tb);
184 } catch {
185 // Do nothing here - The DP should still have its default value
189 public BindingExpressionBase SetBinding (DependencyProperty dp, Binding binding)
191 if (dp == null)
192 throw new ArgumentNullException ("dp");
193 if (binding == null)
194 throw new ArgumentNullException ("binding");
196 BindingExpression e = new BindingExpression (binding, this, dp);
197 binding.Seal ();
198 SetValue (dp, e);
199 return e;
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 {
213 get {
214 return NativeDependencyObjectHelper.FromIntPtr (NativeMethods.framework_element_get_logical_parent (native)) as DependencyObject;
218 internal DependencyObject SubtreeObject {
219 get {
220 return NativeDependencyObjectHelper.FromIntPtr (NativeMethods.uielement_get_subtree_object (native)) as DependencyObject;
224 public event EventHandler<ValidationErrorEventArgs> BindingValidationError;
226 internal virtual void InvokeOnApplyTemplate ()
228 OnApplyTemplate ();
231 internal virtual void InvokeLoaded ()
233 InvalidateLocalBindings ();
234 InvalidateSubtreeBindings ();
237 private Size InvokeMeasureOverride (Size availableSize)
239 try {
240 return MeasureOverride (availableSize);
241 } catch (Exception ex) {
242 try {
243 Console.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeMeasureOverride: {0}", ex);
244 } catch {
245 // Ignore
248 return new Size ();
251 private Size InvokeArrangeOverride (Size finalSize)
253 try {
254 return ArrangeOverride (finalSize);
255 } catch (Exception ex) {
256 try {
257 Console.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeArrangeOverride: {0}", ex);
258 } catch {
259 // Ignore
262 return new Size ();
265 static IntPtr InvokeGetDefaultTemplate (IntPtr fwe_ptr)
267 UIElement root = null;
268 try {
269 FrameworkElement element = (FrameworkElement) NativeDependencyObjectHelper.FromIntPtr (fwe_ptr);
270 root = element.GetDefaultTemplate ();
271 } catch (Exception ex) {
272 try {
273 Console.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeGetDefaultTemplate: {0}", ex);
274 } catch {
275 // Ignore
278 return root == null ? IntPtr.Zero : root.native;
281 static void InvokeLoadedHook (IntPtr fwe_ptr)
283 try {
284 FrameworkElement element = (FrameworkElement) NativeDependencyObjectHelper.FromIntPtr (fwe_ptr);
285 element.InvokeLoaded ();
286 } catch (Exception ex) {
287 try {
288 Console.WriteLine ("Moonlight: Unhandled exception in FrameworkElement.InvokeLoaded: {0}", ex);
289 } catch {
290 // Ignore
295 internal virtual UIElement GetDefaultTemplate ()
297 return null;
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;
315 if (h != null)
316 h (this, e);
319 void RemoveExpression (DependencyProperty dp)
321 Expression e;
322 if (expressions.TryGetValue (dp, out e)) {
323 expressions.Remove (dp);
324 e.Dispose ();
328 internal override void SetValueImpl (DependencyProperty dp, object value)
330 bool addingExpression = false;
331 Expression existing;
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);
366 else {
367 RemoveExpression (dp);
371 try {
372 base.SetValueImpl (dp, value);
373 } catch {
375 if (!addingExpression)
376 throw;
377 else
378 base.SetValueImpl (dp, dp.DefaultValue);
382 internal override object ReadLocalValueImpl (DependencyProperty dp)
384 Expression expression;
385 if (expressions.TryGetValue (dp, out expression))
386 return 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);
459 #endregion