對于一個應(yīng)用系統(tǒng)來說,登錄是最最基本的功能,也是最簡單的功能。本文就Silverlight應(yīng)用的登錄表單來談?wù)勗鯓幼龅阶罴褜嵺`,這也是我學習Silverlight的些許沉淀。
想必會有朋友覺得這么簡單的功能不值得小題大做,其實非也。
首先來看下我專門為此文準備的這個Silverlight Demo的登錄表單:
一個登錄表單無非就是幾個文本框加一個登錄按鈕或取消按鈕而已。而我們都知道對于系統(tǒng)的登錄除了可以單擊登錄按鈕登錄之外,還需要使用回車鍵進行登錄,這基本是每一個登錄表單都具備的功能,缺一不可,如果不提供Enter鍵登錄那就大大降低了用戶體驗。
而本文所探討的則是在Silverlight應(yīng)用中如何去做Enter鍵登錄??赡茏鯝SP.NET開發(fā)的朋友很清楚,ASP.Net中登錄表單的是不需要專門寫代碼來控制Enter鍵登錄的,至于純HTML的Form等等我就不啰嗦了。對于上面這個登錄表單,先看下該表單的XAML構(gòu)成(只貼出重心代碼):
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><TextBlock</span> <span style="color:#0066">Text</span>=<span style="color:#ff00">"用戶名:"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Margin</span>=<span style="color:#ff00">"10 20 5 0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">VerticalAlignment</span>=<span style="color:#ff00">"Center"</span></span>
- <span style="color:#0990"> <span style="color:#0066">HorizontalAlignment</span>=<span style="color:#ff00">"Right"</span> <span style="color:#000000; font-weight:bold">/></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><TextBox</span> <span style="color:#0066">x:Name</span>=<span style="color:#ff00">"userNameBox"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Margin</span>=<span style="color:#ff00">"0 20 0 0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Width</span>=<span style="color:#ff00">"220"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Height</span>=<span style="color:#ff00">"26"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Text</span>=<span style="color:#ff00">"{Binding Path=UserName,Mode=TwoWay,NotifyOnValidationError=True, ValidatesOnExceptions=True}"</span></span>
- <span style="color:#0990"> <span style="color:#0066">TextChanged</span>=<span style="color:#ff00">"userNameBox_TextChanged"</span> <span style="color:#0066">SelectionChanged</span>=<span style="color:#ff00">"userNameBox_SelectionChanged"</span> <span style="color:#000000; font-weight:bold">/></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><TextBlock</span> <span style="color:#0066">Text</span>=<span style="color:#ff00">"密碼:"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Margin</span>=<span style="color:#ff00">"10 0 5 0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">VerticalAlignment</span>=<span style="color:#ff00">"Center"</span></span>
- <span style="color:#0990"> <span style="color:#0066">HorizontalAlignment</span>=<span style="color:#ff00">"Right"</span> <span style="color:#000000; font-weight:bold">/></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><PasswordBox</span> <span style="color:#0066">x:Name</span>=<span style="color:#ff00">"userPwdBox"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Width</span>=<span style="color:#ff00">"220"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Height</span>=<span style="color:#ff00">"26"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Password</span>=<span style="color:#ff00">"{Binding Path=UserPwd,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnExceptions=True}"</span></span>
- <span style="color:#0990"> <span style="color:#0066">PasswordChanged</span>=<span style="color:#ff00">"userPwdBox_PasswordChanged"</span> <span style="color:#000000; font-weight:bold">/></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><Button</span> <span style="color:#0066">x:Name</span>=<span style="color:#ff00">"loginBtn"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Content</span>=<span style="color:#ff00">"登錄"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"2"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.ColumnSpan</span>=<span style="color:#ff00">"2"</span></span>
- <span style="color:#0990"> <span style="color:#0066">HorizontalAlignment</span>=<span style="color:#ff00">"Right"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Width</span>=<span style="color:#ff00">"120"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Height</span>=<span style="color:#ff00">"30"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Margin</span>=<span style="color:#ff00">"0 0 30 0"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Click</span>=<span style="color:#ff00">"loginBtn_Click"</span> <span style="color:#000000; font-weight:bold">/></span></span>
首先,為登錄按鈕添加Click事件,實現(xiàn)單擊登錄按鈕進行登錄。
- <span style="color:#60ff; font-weight:bold">private</span> <span style="color:#6666cc; font-weight:bold">void</span> loginBtn_Click<span style="color:#0800">(</span><span style="color:#6666cc; font-weight:bold">object</span> sender, RoutedEventArgs e<span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- UpdateBindingExpression<span style="color:#0800">(</span>userNameBox, TextBox<span style="color:#0800">.</span><span style="color:#00ff">TextProperty</span><span style="color:#0800">)</span><span style="color:#0800">;</span>
- UpdateBindingExpression<span style="color:#0800">(</span>userPwdBox, PasswordBox<span style="color:#0800">.</span><span style="color:#00ff">PasswordProperty</span><span style="color:#0800">)</span><span style="color:#0800">;</span>
-
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#0800">!</span>loginValidation<span style="color:#0800">.</span><span style="color:#00ff">HasErrors</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#08080; font-style:italic">// 登錄驗證...</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
詳細的邏輯代碼我就省略了。這樣我們就能登錄到系統(tǒng)了,接下來就是本文要談的重點了。因為現(xiàn)在我們是不能通過輸入用戶名和密碼后敲Enter鍵登錄的,我想大家最容易想到的方法便是為userPwd這個PassWordBox添加KeyDown事件:
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><PasswordBox</span> <span style="color:#0066">x:Name</span>=<span style="color:#ff00">"userPwdBox"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Width</span>=<span style="color:#ff00">"220"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Height</span>=<span style="color:#ff00">"26"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Password</span>=<span style="color:#ff00">"{Binding Path=UserPwd,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnExceptions=True}"</span></span>
- <span style="color:#0990"> <span style="color:#0066">PasswordChanged</span>=<span style="color:#ff00">"userPwdBox_PasswordChanged"</span></span>
- <span style="color:#0990"> <span style="color:#0066">KeyDown</span>=<span style="color:#ff00">"userPwdBox_KeyDown"</span> <span style="color:#000000; font-weight:bold">/></span></span>
然后再把上面那個登錄按鈕的代碼Ctrl+C、Ctrl+V到userPwdBox_KeyDown方法體中,最后在添加點判斷敲擊的是不是Enter鍵的代碼。這樣當然可以,因為實現(xiàn)了文本框的Enter鍵登錄。但這樣是不是最佳的解決方案呢?當然不是,那么接下來就來看看本文所說的最佳實踐。
先談?wù)勊悸钒?,從上面的分析知道,既然是基本相同的代碼,那我們應(yīng)該讓文本框在敲下Enter鍵的時候去觸發(fā)登錄按鈕的方法,那么就可以不必再寫同樣的代碼了。這一點應(yīng)該是很容易想到的,那么怎樣實現(xiàn)就需要我們對Silverlight的進一步的了解了。
在Silverlight 3中,Behaviour和Trigger絕對是讓大家比較喜歡的東西了。它們允許你以聲明方式將操作關(guān)聯(lián)到事件或?qū)傩缘闹?。但之前,行為和觸發(fā)器需要我們安裝上 Microsoft Expression Blend SDK ,然后添加System.Windows.Interactivity.dll 程序集的引用。
目前,我們可以使用三種類型的行為: Behavour、 TriggerAction 和 TargetedTriggerAction。在這里,我們使用TargetedTriggerAction<T>泛型類,它表示操作時可以面向一個完全不同的對象,而不受其關(guān)聯(lián)的對象的影響。 它允許我們將觸發(fā)器關(guān)聯(lián)從一個對象到另一個對象,操作完全不同的元素。所以這里就特別適合了。
新建一個TextBoxEnterBehaviour類,繼承自泛型類TargetedTriggerAction<T>,泛型類型為ButtonBase,這里使用ButtonBase是因為它表示所有按鈕控件的基類,例如 Button、RepeatButton 和 HyperlinkButton,更加方便我們擴展。TextBoxEnterBehaviour類的詳細實現(xiàn)如下:
- <span style="color:#60ff; font-weight:bold">public</span> <span style="color:#6666cc; font-weight:bold">class</span> TextBoxEnterBehaviour <span style="color:#0800">:</span> TargetedTriggerAction<span style="color:#0800"><</span>ButtonBase<span style="color:#0800">></span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">private</span> AutomationPeer peer<span style="color:#0800">;</span>
-
- <span style="color:#60ff; font-weight:bold">private</span> ButtonBase targetedButton<span style="color:#0800">;</span>
-
- <span style="color:#08080; font-style:italic">/// <summary></span>
- <span style="color:#08080; font-style:italic">/// 在附加TargetedTriggerAction到關(guān)聯(lián)對象后發(fā)生</span>
- <span style="color:#08080; font-style:italic">/// </summary></span>
- <span style="color:#60ff; font-weight:bold">protected</span> <span style="color:#60ff; font-weight:bold">override</span> <span style="color:#6666cc; font-weight:bold">void</span> OnAttached<span style="color:#0800">(</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">base</span><span style="color:#0800">.</span><span style="color:#00ff">OnAttached</span><span style="color:#0800">(</span><span style="color:#0800">)</span><span style="color:#0800">;</span>
-
- targetedButton <span style="color:#0800">=</span> <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">Target</span><span style="color:#0800">;</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">null</span> <span style="color:#0800">==</span> targetedButton<span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">return</span><span style="color:#0800">;</span>
- <span style="color:#0800">}</span>
- <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">=</span> FrameworkElementAutomationPeer<span style="color:#0800">.</span><span style="color:#00ff">FromElement</span><span style="color:#0800">(</span>targetedButton<span style="color:#0800">)</span><span style="color:#0800">;</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">==</span> <span style="color:#60ff; font-weight:bold">null</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">=</span> FrameworkElementAutomationPeer<span style="color:#0800">.</span><span style="color:#00ff">CreatePeerForElement</span><span style="color:#0800">(</span>targetedButton<span style="color:#0800">)</span><span style="color:#0800">;</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
-
- <span style="color:#08080; font-style:italic">/// <summary></span>
- <span style="color:#08080; font-style:italic">/// 關(guān)聯(lián)的Button改變后發(fā)生</span>
- <span style="color:#08080; font-style:italic">/// </summary></span>
- <span style="color:#08080; font-style:italic">/// <param name="oldTarget"></param></span>
- <span style="color:#08080; font-style:italic">/// <param name="newTarget"></param></span>
-
- <span style="color:#60ff; font-weight:bold">protected</span> <span style="color:#60ff; font-weight:bold">override</span> <span style="color:#6666cc; font-weight:bold">void</span> OnTargetChanged<span style="color:#0800">(</span>ButtonBase oldTarget, ButtonBase newTarget<span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">base</span><span style="color:#0800">.</span><span style="color:#00ff">OnTargetChanged</span><span style="color:#0800">(</span>oldTarget, newTarget<span style="color:#0800">)</span><span style="color:#0800">;</span>
-
- targetedButton <span style="color:#0800">=</span> newTarget<span style="color:#0800">;</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">null</span> <span style="color:#0800">==</span> targetedButton<span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">return</span><span style="color:#0800">;</span>
- <span style="color:#0800">}</span>
- <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">=</span> FrameworkElementAutomationPeer<span style="color:#0800">.</span><span style="color:#00ff">FromElement</span><span style="color:#0800">(</span>targetedButton<span style="color:#0800">)</span><span style="color:#0800">;</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">==</span> <span style="color:#60ff; font-weight:bold">null</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">=</span> FrameworkElementAutomationPeer<span style="color:#0800">.</span><span style="color:#00ff">CreatePeerForElement</span><span style="color:#0800">(</span>targetedButton<span style="color:#0800">)</span><span style="color:#0800">;</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
-
- <span style="color:#08080; font-style:italic">/// <summary></span>
- <span style="color:#08080; font-style:italic">/// 激活targeted Button并啟動targeted Button的單個明確操作</span>
- <span style="color:#08080; font-style:italic">/// </summary></span>
- <span style="color:#08080; font-style:italic">/// <param name="parameter"></param></span>
-
- <span style="color:#60ff; font-weight:bold">protected</span> <span style="color:#60ff; font-weight:bold">override</span> <span style="color:#6666cc; font-weight:bold">void</span> Invoke<span style="color:#0800">(</span><span style="color:#6666cc; font-weight:bold">object</span> parameter<span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- KeyEventArgs keyEventArgs <span style="color:#0800">=</span> parameter <span style="color:#60ff; font-weight:bold">as</span> KeyEventArgs<span style="color:#0800">;</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">null</span> <span style="color:#0800">!=</span> keyEventArgs <span style="color:#0800">&&</span> keyEventArgs<span style="color:#0800">.</span><span style="color:#00ff">Key</span> <span style="color:#0800">==</span> Key<span style="color:#0800">.</span><span style="color:#00ff">Enter</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- <span style="color:#60ff; font-weight:bold">if</span> <span style="color:#0800">(</span><span style="color:#60ff; font-weight:bold">null</span> <span style="color:#0800">!=</span> <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span> <span style="color:#0800">&&</span> <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span><span style="color:#0800">.</span><span style="color:#00ff">IsEnabled</span><span style="color:#0800">(</span><span style="color:#0800">)</span><span style="color:#0800">)</span>
- <span style="color:#0800">{</span>
- IInvokeProvider invokeProvider <span style="color:#0800">=</span> <span style="color:#60ff; font-weight:bold">this</span><span style="color:#0800">.</span><span style="color:#00ff">peer</span><span style="color:#0800">.</span><span style="color:#00ff">GetPattern</span><span style="color:#0800">(</span>PatternInterface<span style="color:#0800">.</span><span style="color:#00ff">Invoke</span><span style="color:#0800">)</span> <span style="color:#60ff; font-weight:bold">as</span> IInvokeProvider<span style="color:#0800">;</span>
- invokeProvider<span style="color:#0800">.</span><span style="color:#00ff">Invoke</span><span style="color:#0800">(</span><span style="color:#0800">)</span><span style="color:#0800">;</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
- <span style="color:#0800">}</span>
然后為userPwdBox添加觸發(fā)器。首先在該登錄表單的XAML中添加如下聲明:
- xmlns:interaction="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
- xmlns:behaviour="clr-namespace:SLDemo" (這個為TextBoxEnterBehaviour類所在命名空間)
然后修改userPwdBox為如下代碼:
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><PasswordBox</span> <span style="color:#0066">x:Name</span>=<span style="color:#ff00">"userPwdBox"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Row</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Grid.Column</span>=<span style="color:#ff00">"1"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Width</span>=<span style="color:#ff00">"220"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Height</span>=<span style="color:#ff00">"26"</span></span>
- <span style="color:#0990"> <span style="color:#0066">Password</span>=<span style="color:#ff00">"{Binding Path=UserPwd,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnExceptions=True}"</span></span>
- <span style="color:#0990"> <span style="color:#0066">PasswordChanged</span>=<span style="color:#ff00">"userPwdBox_PasswordChanged"</span><span style="color:#000000; font-weight:bold">></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><interaction:Interaction.Triggers<span style="color:#000000; font-weight:bold">></span></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><interaction:EventTrigger</span> <span style="color:#0066">EventName</span>=<span style="color:#ff00">"KeyDown"</span><span style="color:#000000; font-weight:bold">></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"><behaviour:TextBoxEnterBehaviour</span> <span style="color:#0066">TargetName</span>=<span style="color:#ff00">"loginBtn"</span> <span style="color:#000000; font-weight:bold">/></span></span> (TargetName為關(guān)聯(lián)的登錄按鈕的Name屬性值)
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"></interaction:EventTrigger<span style="color:#000000; font-weight:bold">></span></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"></interaction:Interaction.Triggers<span style="color:#000000; font-weight:bold">></span></span></span>
- <span style="color:#0990"><span style="color:#000000; font-weight:bold"></PasswordBox<span style="color:#000000; font-weight:bold">></span></span></span>
這樣便通過很好的方法實現(xiàn)了Silverlight應(yīng)用中的文本框回車登錄。因為這樣真正避免了重復(fù)代碼
原文地址:http://www.heroicyang.com/archives/2010/06/01/%E6%B5%85%E8%B0%88silverlight%E5%BA%94%E7%94%A8%E4%B9%8B%E5%9B%9E%E8%BD%A6%E7%99%BB%E5%BD%95%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.html