Wie kann ich in Silverlight in Dialogen einen Default-Button festlegen?
Veröffentlicht: 02. Jun 2010
Das Problem
Es ist Gang und Gäbe, dass zum Beispiel beim Ausfüllen eines Formulars nur die <Enter>-Taste gedrückt werden muss und eine bestimmte Aktion wird ausgelöst. Dieser How-To-Guide beschreibt, wie man in einer Silverlight-Anwendung einen Default-Button festlegt, der ausgelöst wird, wenn der Benutzer <Enter> drückt.
Die Lösung
- Erstellen Sie im Visual Studio 2010 eine neue Silverlight-Anwendung. In diesem Beispiel wird der Projektname DefaultButtonCs verwendet.
- Fügen Sie der MainPage.xaml eine TextBox und einen Button hinzu, der ausgelöst werden soll, wenn in der TextBox die <Enter>-Taste gedrückt wird. Geben Sie dem Button den Namen „defaultButton“ und implementieren Sie im EvenHandler des Clicked-Events die Logik, die ausgeführt werden soll, wenn auf den Button gedrückt wird. In diesem Beispiel wird eine MessageBox mit einer Meldung angezeigt.
- Fügen Sie dem Projekt einen Verweis auf die System.Windows.Interactivity.dll aus dem Expression SDK hinzu.
- Erstellen Sie in einer neuen Datei DefaultButtonTrigger.cs einen Namespace DefaultButtonCs.Triggers
- In diesem Namespace erstellen Sie eine Klasse DefaultButtonTrigger, die von der Klasse TargetedTriggerAction<ButtonBase> ableitet.
- Implementieren Sie in dieser Klasse zwei private Felder: _peer vom Typ AutomationPeer und _targetedButton vom Typ ButtonBase.
- Überschreiben Sie in dieser Klasse die Methoden OnAttached() und OnTargetChanged(...) und implementieren Sie in beiden Fällen folgende Logik, welche die Eigenschaften _peer und _targetedButton füllt.
- Überschreiben Sie ebenfalls die Methode Invoke(object parameter). Als Parameter werden beim Aufruf die KeyEventArgs des KeyDown-Events übergeben werden. Überprüfen Sie, ob die <Enter>-Taste gedrückt wurde und lösen Sie auf dem Peer die Invoke()-Methode aus, wenn das dies Fall ist.
- Referenzieren Sie in der MainPage.xaml die XML-Namespaces interactivity aus der Assembly System.Windows.Interactivity und triggers aus dem Namespace DefaultButtonCS.Triggers des Projekts.
- Fügen Sie dem TextBox-Element folgendes XAML-Markup hinzu, um einen Trigger für das KeyDown-Event auf den defaultButton einzurichten:
- Starten Sie das Projekt. Vergleichen Sie das Verhalten, wenn Sie den Button durch einen Mausklick auslösen mit dem Ergebnis, wenn Sie den Fokus in die TextBox setzen und die <Enter>-Taste drücken.
targetedButton = this.Target;
if (null == _targetedButton) return;
_peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (_peer == null)
{
_peer = FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
KeyEventArgs keyEventArgs = parameter as KeyEventArgs;
if (null != keyEventArgs && keyEventArgs.Key == Key.Enter)
{
if (null != _peer && _peer.IsEnabled())
{
IInvokeProvider invokeProvider
=_peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProvider.Invoke();
}
}
<TextBox>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="KeyDown">
<triggers:DefaultButtonTrigger TargetName="defaultButton" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</TextBox>
Der Code
MainPage.xaml
<UserControl x:Class="DefaultButtonCs.MainPage"
...
xmlns:interactivity="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:triggers="clr-namespace:DefaultButtonCs.Triggers"
...>
...
<TextBox>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="KeyDown">
<triggers:DefaultButtonTrigger TargetName="defaultButton" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</TextBox>
...
<Button x:Name="defaultButton" Content="Default-Button"
Click="defaultButton_Click"/>
...
</UserControl>
MainPage.xaml.cs
namespace DefaultButtonCs
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void defaultButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Default-Button gedrückt.");
}
}
}
DefaultButtonTrigger.cs
...
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls.Primitives;
using System.Windows.Interactivity;
namespace DefaultButtonCs.Triggers
{
public class DefaultButtonTrigger : TargetedTriggerAction<ButtonBase>
{
private AutomationPeer _peer { get; set; }
private ButtonBase _targetedButton { get; set; }
protected override void OnAttached()
{
base.OnAttached();
_targetedButton = this.Target;
if (null == _targetedButton) return;
_peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (_peer == null)
{
_peer =
FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}
protected override void OnTargetChanged(ButtonBase oldTarget,
ButtonBase newTarget)
{
base.OnTargetChanged(oldTarget, newTarget);
_targetedButton = newTarget;
if (null == _targetedButton) return;
_peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (_peer == null)
{
_peer =
FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}
protected override void Invoke(object parameter)
{
KeyEventArgs keyEventArgs = parameter as KeyEventArgs;
if (null != keyEventArgs && keyEventArgs.Key == Key.Enter)
{
if (null != _peer && _peer.IsEnabled())
{
IInvokeProvider invokeProvider = _peer.GetPattern(PatternInterface.Invoke)
as IInvokeProvider;
invokeProvider.Invoke();
}
}
}
}
}
Voraussetzungen
Microsoft Expression SDK
http://www.microsoft.com/downloads/details.aspx?FamilyID=f1ae9a30-4928-411d-970b-e682ab179e17&DisplayLang=de