1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Presentation.View
8 using System.Collections.Generic;
12 using System.Windows.Controls;
13 using System.Windows.Data;
14 using System.Windows.Documents;
15 using System.Windows.Input;
16 using System.Windows.Media;
17 using System.Windows.Media.Imaging;
18 using System.Windows.Navigation;
19 using System.Windows.Shapes;
20 using System.Activities.Presentation.View;
21 using System.ComponentModel;
22 using System.Windows.Automation.Peers;
23 using System.Xml.Linq;
24 using System.Reflection;
26 partial class VBIdentifierDesigner : UserControl
28 public static readonly DependencyProperty IdentifierProperty =
29 DependencyProperty.Register("Identifier", typeof(VBIdentifierName), typeof(VBIdentifierDesigner), new UIPropertyMetadata(OnIdentifierChanged));
31 public static readonly DependencyProperty NameStringProperty =
32 DependencyProperty.Register("NameString", typeof(string), typeof(VBIdentifierDesigner), new UIPropertyMetadata(null, null, OnNameChanging));
34 public static readonly DependencyProperty IsReadOnlyProperty =
35 DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(VBIdentifierDesigner));
37 public event PropertyChangedEventHandler TextBoxPropertyChanged;
40 bool isInternalChange;
41 bool checkAgainstXaml;
43 public VBIdentifierName Identifier
45 get { return (VBIdentifierName)GetValue(IdentifierProperty); }
46 set { SetValue(IdentifierProperty, value); }
49 public string NameString
51 get { return (string)GetValue(NameStringProperty); }
52 set { SetValue(NameStringProperty, value); }
55 public bool IsReadOnly
57 get { return (bool)GetValue(IsReadOnlyProperty); }
58 set { SetValue(IsReadOnlyProperty, value); }
61 internal TextBox IdentifierTextBox
69 if (value != this.textBox)
72 if (this.TextBoxPropertyChanged != null)
74 this.TextBoxPropertyChanged(this, new PropertyChangedEventArgs("IdentifierTextBox"));
80 public VBIdentifierDesigner()
82 InitializeComponent();
83 this.Loaded += (s, e) =>
85 //when designer gets loaded, get its identifier binding expression with parent control
86 var binding = this.GetBindingExpression(VBIdentifierDesigner.IdentifierProperty);
87 if (null != binding && null != binding.ParentBinding)
89 //if one exists - define update source exception filter
90 binding.ParentBinding.UpdateSourceExceptionFilter = this.OnBindingException;
96 void OnTextBoxLoaded(object sender, RoutedEventArgs e)
98 this.IdentifierTextBox = sender as TextBox;
99 this.IdentifierTextBox.LostKeyboardFocus += this.OnTextBoxLostKeyboardFocus;
102 void OnTextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
104 if (this.IdentifierTextBox.IsFocused)
106 DependencyObject focusScope = FocusManager.GetFocusScope(this.IdentifierTextBox);
107 FocusManager.SetFocusedElement(focusScope, this);
111 void OnTextBoxUnloaded(object sender, RoutedEventArgs e)
113 TextBox textBox = sender as TextBox;
114 textBox.LostKeyboardFocus -= this.OnTextBoxLostKeyboardFocus;
115 this.IdentifierTextBox = null;
118 object OnBindingException(object sender, Exception err)
120 //whenever exception occurs, allow ValidationException to be rethrown - this exception is needed to revert invalid value
121 if (err is TargetInvocationException && err.InnerException is ValidationException || err is ValidationException)
123 throw FxTrace.Exception.AsError( err.InnerException ?? err );
125 //simply return null - we don't use error template for this control
129 static object OnNameChanging(DependencyObject sender, object newValue)
131 var ctrl = (VBIdentifierDesigner)sender;
132 //before allowing new value to be assigned to property, check if it passes validation
133 return ctrl.OnNameChanging(ctrl.NameString, (string)newValue);
136 object OnNameChanging(string oldName, string newName)
138 string result = newName;
139 if (!this.isInternalChange)
143 this.isInternalChange = true;
144 //try to create new Identifier - if this call succeds, set the new value to a property
145 this.Identifier = new VBIdentifierName(this.checkAgainstXaml) { IdentifierName = newName };
147 catch (ValidationException)
149 //in case of validation exception - do not allow new invalid value to be set
151 //if text box is still visible - refresh its Text property to old value
152 if (null != this.textBox)
154 var binding = this.textBox.GetBindingExpression(TextBox.TextProperty);
155 binding.UpdateTarget();
160 this.isInternalChange = false;
166 static void OnIdentifierChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
168 (sender as VBIdentifierDesigner).OnIdentifierChanged();
171 void OnIdentifierChanged()
173 if (!this.isInternalChange && null != this.Identifier)
175 this.isInternalChange = true;
176 this.NameString = this.Identifier.IdentifierName;
177 this.isInternalChange = false;
178 this.checkAgainstXaml = this.Identifier.CheckAgainstXaml;
182 protected override AutomationPeer OnCreateAutomationPeer()
184 return new VBIdentiferDesignerAutomationPeer(this);
188 class VBIdentiferDesignerAutomationPeer : UIElementAutomationPeer
190 public VBIdentiferDesignerAutomationPeer(VBIdentifierDesigner owner)
195 protected override string GetItemStatusCore()
197 VBIdentifierDesigner vbIdentifierDesigner = this.Owner as VBIdentifierDesigner;
198 if (vbIdentifierDesigner != null)
200 VBIdentifierName vbIdentifier = vbIdentifierDesigner.Identifier;
201 if (vbIdentifier != null)
203 XElement itemStatus = new XElement("VBIdentifierStatus",
204 new XAttribute("Status", vbIdentifier.IsValid ? "Valid" : "Invalid"),
205 new XAttribute("WarningMessage", vbIdentifier.ErrorMessage));
206 return itemStatus.ToString();
209 return base.GetItemStatusCore();