Поэтому я должен признать, что у меня был рабочий ответ, когда я это написал, но мне потребовалось много времени, чтобы понять это, поэтому я размещаю его здесь, надеясь, что это поможет кому-то еще, хотя это очень специфический сценарий.
Я использую модель MVVM для своего приложения, поэтому я не хочу иметь код за страницами xaml. Я также хотел, чтобы привязка текстового поля к свойствам IDataErrorInfo, где проверка для этого текстового поля запускается через событие lostfocus в текстовом поле. Это событие будет привязано к команде ретрансляции в режиме просмотра, которая будет проверять применимый объект и добавлять реальные ошибки.
Так что мне нужно, чтобы текстовое поле lostfocus eventcommand принимало имя текстового поля (которое соответствует именам столбцов из базы данных) в качестве параметра команды.
Вот снимок экрана, что я пытаюсь сделать ![WPF Screen Shot of Textbox Validation STyle](https://i.stack.imgur.com/oksC0.jpg)
Вот как я это сделал:
Сначала я определил команду на модели представления:
Imports GalaSoft.MvvmLight.Command
Private _LostFocusValidateCommand As RelayCommand(Of String)
Public ReadOnly Property LostFocusValidateCommand() As RelayCommand(Of String)
Get
If _LostFocusValidateCommand Is Nothing Then
_LostFocusValidateCommand = New RelayCommand(Of String)(AddressOf LostFocusValidateExecute)
End If
Return _LostFocusValidateCommand
End Get
End Property
Private Sub LostFocusValidateExecute(sParam As String)
NewClient.PropertyValitaion(False, sParam)
End Sub
здесь это проверка свойств с использованием IDataErrorInfo (я упустил базовую реализацию IDataErrorInfo для экономии места, оставьте комментарий, если вы хотите, чтобы я опубликовал его)
Public Sub PropertyValitaion(bAllProperties As Boolean, Optional sProperty As String = "")
'initialize validation helper
Dim vhelper As New ValidationHelper
If bAllProperties Or sProperty = "chrCompany" Then
If String.IsNullOrEmpty(chrCompany) Then
AddError("chrCompany", "You must enter a Company Name")
Else
RemoveError("chrCompany")
End If
End If
If bAllProperties Or sProperty = "chrFirst" Then
If String.IsNullOrEmpty(chrFirst) Then
AddError("chrFirst", "You must enter a First Name")
Else
RemoveError("chrFirst")
End If
End If
If bAllProperties Or (sProperty = "chrPhone1" Or sProperty = "chrPhone1Ext") Then
If String.IsNullOrEmpty(Trim(chrPhone1Ext)) = False And String.IsNullOrEmpty(Trim(chrPhone1)) Then
Me.AddError("chrPhone1", "Provide a phone number or remove extension")
Else
RemoveError("chrPhone1")
End If
If String.IsNullOrEmpty(Trim(chrPhone1)) = False Then
If vhelper.CheckPhoneNumber(Me.chrPhone1) = False Then
Me.AddError("chrPhone1", "Phone 1 format invalid")
Else
RemoveError("chrPhone1")
End If
End If
End If
End Sub
Жесткая часть выясняла, как определить стиль. Стиль давно, извините, радостей «читаемым» XML:
<Style x:Key="FTC_ValidateTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Style.Setters>
<Setter Property="FontFamily" Value="Open Sans Condensed"/>
<Setter Property="FontSize" Value="19" />
<Setter Property="Margin" Value="3,3,15,6"/>
<Setter Property="Padding" Value="10,3"/>
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="{StaticResource DetailTextBox}" />
<Setter Property="BorderBrush" Value="{StaticResource MediumGray}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Name="Bd" SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<cmd:EventToCommand Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.LostFocusValidateCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBox}},Path=Name}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="{StaticResource MediumRed}" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<AdornedElementPlaceholder Name="parentTextBox" />
<TextBlock Grid.Row="1" Style="{StaticResource FTC_DetailError}"
Text="{Binding ElementName=parentTextBox, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
<Setter Property="BorderBrush" Value="{StaticResource MediumRed}"/>
<Setter Property="Foreground" Value="{StaticResource MediumRed}"/>
<Setter Property="Margin" Value="3,3,15,31"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="FTC_DetailError" TargetType="TextBlock">
<Style.Setters>
<Setter Property="FontFamily" Value="Open Sans Condensed"/>
<Setter Property="Control.FontWeight" Value="Light" />
<Setter Property="Foreground" Value="{StaticResource TitleWhite}"/>
<Setter Property="FontSize" Value="15" />
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="10,3"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource MediumRed}"/>
</Style.Setters>
</Style>
все волшебство происходит в шаблоне свойства.Следующие должны быть включены в верхней декларациях словаря ресурсов:
> xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
> xmlns:cmd="http://www.galasoft.ch/mvvmlight"
все волшебство происходит в свойстве шаблона, который определяет шаблон элемента управления. Вы не можете обернуть i: взаимодействие в самом шаблоне управления, оно должно содержаться в производном объекте, почти на самом деле, границе, scrollviewer, wrappanel и т. Д. Затем вы устанавливаете триггер вентиляции и свойства команды. Они должны быть достаточно легкими, чтобы следовать, я передаю имя текстового поля в качестве параметра команды. Клиентский «ящик», который вы видите на снимке экрана, представляет собой сетку с контекстом данных, установленным для нового свойства объекта-клиента родительской модели. SO, чтобы получить доступ к команде в родительской модели просмотра, мне пришлось ссылаться на datacontext родителя и вызвать свойство command.
Опять же, я понимаю, что это очень специфический сценарий, но я подумал, что у него есть несколько примеров, которые могли бы помочь другим. Теперь я могу определить один стиль для всех текстовых полей в приложении, которые являются вводом данных, и что я хочу инициировать основные процедуры проверки. Это избавит меня от необходимости определять поведение пользовательской команды во всех этих текстовых полях отдельно, и все это выполняется в xaml, без кода.
Cheers