AutoCompleteBox et INotifyDataErrorInfo dans Silverlight
-
26-10-2019 - |
Question
Quelqu'un at-il appliqué avec succès l'interface INotifyDataErrorInfo et lié à un AutoCompleteBox. Je l'ai essayé, mais je ne reçois aucune réponse. Le contrôle ne répond pas que d'autres contrôles à savoir avec une bordure rouge et une info-bulle d'avertissement. Il ne fait pas l'écran de contrôle sommaire de validation avec l'erreur.
J'ai mis avec succès TextBoxes standard et datepickers et ceux-ci se comportent parfaitement que par les nombreux exemples fournis gracieusement par des personnes sur Internet.
il serait bon s'il y avait une réponse à cette question pour la cohérence de mon écran, aussi parce que je voudrais simplement se lient à la propriété HasErrors qui vient avec INotifyDataErrorInfo pour permettre un bouton lorsque vous êtes prêt à enregistrer et je ne peux pas faire sans code supplémentaire pour vérifier que ces boîtes sont correctes.
Au moment où je traite ces différentes en utilisant un MVVMLight EventToCommand obligatoire et l'enregistrement de l'événement LostFocus.
<sdk:AutoCompleteBox x:Name="TransferTypeTextBox" SelectedItem="{Binding Path=SelectedTransferType, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True}" ItemsSource="{Binding Path=TransferTypes}" IsTextCompletionEnabled="True" Grid.Row="1" Grid.Column="1" Margin="0,3" Width="238" HorizontalAlignment="Left" FontFamily="/PtrInput_Silverlight;component/Fonts/Fonts.zip#Calibri" FontSize="13.333">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<cmd:EventToCommand Command="{Binding TransferTypeLostFocusCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</sdk:AutoCompleteBox>
Dans le ViewModel je puis jeté le RoutedEventArgs.OriginalSource à une zone de texte et obtenir le texte comme si, ce qui empêche l'utilisateur de quitter la zone à moins qu'il soit vide ou correspondant à un élément dans la liste de la boîte: -
private void OnTransferTypeLostFocus(RoutedEventArgs e)
{
System.Windows.Controls.TextBox box = (System.Windows.Controls.TextBox)e.OriginalSource;
// If user inputs text but doesn't select one item, show message.
if (this.Ptr.TransferType == null && !string.IsNullOrEmpty(box.Text))
{
MessageBox.Show("That is not a valid entry for Transfer Type", "Transfer type", MessageBoxButton.OK);
box.Focus();
}
}
La solution
Je l'ai essayé d'écrire comme exemple simple que je peux. Mon modèle d'observer les changements de la propriété searchtext et mise à jour des propriétés de validation.
public class MainViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
{
private Dictionary<string, List<string>> ErrorMessages = new Dictionary<string, List<string>>();
public MainViewModel()
{
//Validation works automatically for all properties that notify about the changes
this.PropertyChanged += new PropertyChangedEventHandler(ValidateChangedProperty);
}
//Validate and call 'OnErrorChanged' for reflecting the changes in UI
private void ValidateChangedProperty(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "HasErrors") //avoid recursion
return;
this.ValidateProperty(e.PropertyName);
OnErrorsChanged(e.PropertyName);
OnPropertyChanged("HasErrors");
}
//Just compare a received value with a correct value, it's a simple rule for demonstration
public void ValidateProperty(string propertyName)
{
if (propertyName == "SearchText")
{
this.ErrorMessages.Remove(propertyName);
if (SearchText != "Correct value")
this.ErrorMessages.Add("SearchText", new List<string> { "Enter a correct value" });
}
}
private string searchText;
public string SearchText
{
get { return searchText; }
set
{
searchText = value;
OnPropertyChanged("SearchText");
}
}
#region INotifyDataErrorInfo
public IEnumerable GetErrors(string propertyName)
{
return this.ErrorMessages.Where(er => er.Key == propertyName).SelectMany(er => er.Value);
}
public bool HasErrors
{
get { return this.ErrorMessages.Count > 0; }
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };
private void OnErrorsChanged(string propertyName)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
#endregion
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void OnPropertyChanged(string propertyName)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Et XAML:
<sdk:AutoCompleteBox Text="{Binding SearchText, Mode=TwoWay}" />
<Button IsEnabled="{Binding HasErrors, Converter={StaticResource NotConverter}}" Content="Save"/>
Le contrôle a une bordure rouge et le bouton est désactivé lorsque le modèle comporte des erreurs.