添付プロパティは、必要なものへの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}" />