2012-06-04 47 views
3

我爲一些自定義的WPF控件構建了一系列事件處理程序。該事件處理當用戶根據包含的數據類型(電話號碼,郵政編碼,貨幣值等)輸入或離開文本框時顯示的文本的格式。另一個類中的WPF事件處理程序

現在我已將所有事件直接附加到xaml的C#代碼。因爲我開發了一個可以控制的控件,這意味着邏輯重複了很多次,如果我想改變程序範圍的功能,我將不得不在任何地方對事件代碼進行更改。

我確定有一種方法可以將我的所有事件處理函數放在一個類中。任何人都可以幫助我指出正確的方向嗎?

我看到這篇文章:Event Handler located in different class than MainWindow但我不確定它是否直接關係到我在做什麼。我寧願對現有的邏輯做一些小的改變,因爲它有效,然後把所有的東西都改寫成命令。

我基本上希望這樣的事情如果可能的話:

LostFocus="ExpandedTextBoxEvents.TextBox_LostFocus" 

這是很容易做這樣的事情:

private void TextBoxCurrencyGotFocus(object sender, RoutedEventArgs e) 
{ 
    ExpandedTextBoxEvents.TextBoxCurrencyGotFocus(sender, e); 
} 
private void TextBoxCurrencyLostFocus(object sender, RoutedEventArgs e) 
{ 
    ExpandedTextBoxEvents.TextBoxCurrencyLostFocus(sender, e); 
} 

但這是那麼優雅。

+0

您想對多個TextBox項使用通用代碼,以便它們的行爲相同嗎?在這種情況下,你很可能繼承TextBox的子類,然後使用這個自定義類。例如,如果它是電話號碼的TextBox,則可以將其命名爲「PhoneNumberTextBox」。 –

+0

LostFocus不是DependencyProperty,它是一個事件,所以你不能將值綁定到它。當XAML解析器讀取LostFocus的XAML屬性中的文本時,它將使用反射來查找基類中具有相同名稱的方法。據我所知,沒有辦法來覆蓋這種行爲,也不會這樣做。您最好的選擇是使用下面介紹的解決方案之一。 – JDB

回答

1

Attached Properties是您想要的一種方法。我經常使用它們。

附加屬性代碼:

Public Class TextBoxFormatter 

    ' ------------------------------------------------------ 
    ' Define the FormatType attached property 

    Public Shared ReadOnly FormatTypeProperty As DependencyProperty = _ 
     DependencyProperty.RegisterAttached(_ 
      name:="FormatType", _ 
      propertyType:=GetType(TextBoxFormatterType), _ 
      ownerType:=GetType(TextBoxFormatter), _ 
      defaultMetadata:=New FrameworkPropertyMetadata(_ 
       defaultValue:=TextBoxFormatterType.None, _ 
       PropertyChangedCallback:=New PropertyChangedCallback(AddressOf FormatTypePropertyChanged) _ 
      ) _ 
     ) 
    ' ------------------------------------------------------ 
    ' Define the "getter" and "setter" for FormatType 
    Public Shared Function GetFormatType(ByVal target As DependencyObject) As TextBoxFormatterType 
     target.GetValue(FormatTypeProperty) 
    End Function 
    Public Shared Sub SetFormatType(ByVal target As DependencyObject, ByVal value As TextBoxFormatterType) 
     target.SetValue(FormatTypeProperty, value) 
    End Sub 

    ' ------------------------------------------------------ 
    ' Define the FormatType "PropertyChanged" event handler 

    Private Shared Sub FormatTypePropertyChanged(ByVal target As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) 
     If CType(e.NewValue, TextBoxFormatterType) = TextBoxFormatterType.None Then 
      UnregisterFormatTypeControl(target) 
     Else 
      RegisterFormatTypeControl(target) 
     End If 
    End Sub 

    ' ------------------------------------------------------ 
    ' Define the a collection of event listerns for the 
    ' FormatType "PropertyChanged" event 

    Private Shared _registeredFormatTypeControlDelegates As New Dictionary(Of TextBox, RoutedEventHandler) 

    ' ------------------------------------------------------ 
    ' Register a control as an event listener 
    ' (also, attach to the control's LostFocus event) 

    Private Shared Sub RegisterFormatTypeControl(ByVal candidate As DependencyObject) 
     Dim l_control = TryCast(candidate, TextBox) 
     If l_control IsNot Nothing Then 
      Dim l_handler = New RoutedEventHandler(AddressOf FormatTypeControl_LostFocus) 
      _registeredFormatTypeControlDelegates.Add(l_control, l_handler) 
      l_control.AddHandler(TextBox.LostFocusEvent, l_handler) 
     End If 
    End Sub 

    ' ------------------------------------------------------ 
    ' Unregister a control as an event listener 
    ' (also, unattach from the control's LostFocus event) 

    Private Shared Sub UnregisterFormatTypeControl(ByVal candidate As DependencyObject) 
     Dim l_control = TryCast(candidate, TextBox) 
     If l_control IsNot Nothing AndAlso _registeredFormatTypeControlDelegates.ContainsKey(l_control) Then 
      Dim l_handler = _registeredFormatTypeControlDelegates(l_control) 
      l_control.RemoveHandler(TextBox.LostFocusEvent, l_handler) 
      _registeredFormatTypeControlDelegates.Remove(l_control) 
     End If 
    End Sub 

    ' ------------------------------------------------------ 
    ' On the control's LostFocus event, apply the format 
    ' (You could apply the format based on another event, 
    ' just be careful if using the TextChanged event - it 
    ' will fire whether the user has changed the text or 
    ' your code has changed the text - could introduce an 
    ' infinite loop) 

    Private Shared Sub FormatTypeControl_LostFocus(ByVal sender As Object, ByVal e As RoutedEventArgs) 
     Dim l_textBox = TryCast(e.Source, TextBox) 
     If l_textBox IsNot Nothing Then 

      Dim l_formatType = CType(l_textBox.GetValue(FormatTypeProperty), TextBoxFormatterType) 
      Select Case l_formatType 

       Case TextBoxFormatterType.SocialSecurityNumber 
        ' Apply the format to the l_textBox 
        ' (What do you want a social security number to look like?) 

       Case TextBoxFormatterType.ZipCode 
        ' Apply the format to the l_textBox 
        ' (What do you want a zip code to look like?) 

       Case TextBoxFormatterType.Etc 
        ' Apply the format to the l_textBox 

      End Select 

     End If 
    End Sub 

End Class 

Public Enum TextBoxFormatterType 
    None 
    ZipCode 
    SocialSecurityNumber 
    Etc 
End Enum 

上面看起來有點雜亂,但一旦代碼被寫入(一次),你可以在你的UI一遍又一遍用它:

<Window x:Class="Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:this="clr-namespace:WpfApplication1" 
     Title="Window1"> 
    <Grid> 

    <StackPanel> 

     <TextBox this:TextBoxFormatter.FormatType="SocialSecurityNumber" /> 
     <TextBox this:TextBoxFormatter.FormatType="ZipCode" /> 
     <TextBox this:TextBoxFormatter.FormatType="None" /> 

    </StackPanel> 

    </Grid> 
</Window> 

這種方法的一個優點是「FormatType」成爲一個依賴屬性,這意味着您可以在運行時將值綁定到它(而不僅僅是像上面的示例那樣進行編碼)。例如:

<TextBox this:TextBoxFormatter.FormatType="{Binding ViewModel.DesiredFormat}" /> 
2

您可以創建一個依賴屬性,並在XAML像這樣使用它:

ExpandedTextBoxEvents.Subscribe="True" 

依賴屬性將存在於ExpandedTextBoxEvents類和訂閱屬性可以建立所有必要的事件訂閱時,它得到設置爲True

這會讓您有一個單獨的類,由一個簡單的語句通過XAML(或C#,如果您願意的話)拉入。

相關問題