3

いくつかのカスタム WPF コントロール用に一連のイベント ハンドラーを作成しました。イベント ハンドルは、含まれるデータの種類 (電話番号、郵便番号、金額など) に基づいて、ユーザーがテキスト ボックスに出入りするときに表示されるテキストをフォーマットします。

現在、xaml に直接アタッチされた C# コードにローカルですべてのイベントがあります。私はできたコントロールを開発したので、これはロジックが何度も繰り返されることを意味し、プログラム全体の機能を変更したい場合は、イベント コードが配置されているすべての場所で変更を行う必要があります。

すべてのイベント ハンドラーを単一のクラスに配置する方法があると確信しています。誰かが私を正しい方向に向けるのを助けることができますか?

この記事を見ました: 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);
}

しかし、それはエレガントではありません。

4

2 に答える 2

2

添付プロパティは、必要なものへの1つのアプローチです。よく使います。

添付のプロパティコード:

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

上記は少し雑然としているように見えますが、コードが(1回)記述されると、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>

このアプローチの利点の1つは、「FormatType」が依存関係プロパティになることです。つまり、実行時に値をバインドできます(上記の例のようにハーコーディングするだけではありません)。例えば:

<TextBox this:TextBoxFormatter.FormatType="{Binding ViewModel.DesiredFormat}" />
于 2012-06-04T17:09:01.037 に答える
2

依存関係プロパティを作成し、次のように XAML で使用できます。

ExpandedTextBoxEvents.Subscribe="True"

依存関係プロパティはExpandedTextBoxEventsクラスに存在し、Subscribe プロパティが に設定されると、必要なすべてのイベント サブスクリプションを確立できますTrue

これにより、1 つの簡単なステートメントで XAML (または必要に応じて C#) によって引き出された個別のクラスが残ります。

于 2012-06-04T16:37:26.673 に答える