AutoCompleteBox и INotifyDataErrorInfo в Silverlight - PullRequest
1 голос
/ 27 января 2011

Кто-нибудь успешно применил интерфейс INotifyDataErrorInfo и привязал его к AutoCompleteBox. Я пробовал это, но я не получил ответа. Элемент управления не отвечает как другие элементы управления, то есть с красной рамкой и всплывающей подсказкой. Он также не отображает элемент управления Сводка проверки со своей ошибкой.

Я успешно настроил стандартные TextBoxes и DatePickers, и они ведут себя отлично, как и многие примеры, любезно предоставленные людьми в Интернете.

было бы хорошо, если бы был ответ на этот вопрос для согласованности моего экрана, а также потому, что я хотел бы просто привязать свойство HasErrors, которое поставляется с INotifyDataErrorInfo, чтобы включить кнопку, когда она готова к сохранению, и я не могу сделайте это без дополнительного кода, чтобы проверить правильность этих полей.

В настоящий момент я рассматриваю их по-разному, используя привязку MVVMLight EventToCommand и регистрируя событие 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>

В ViewModel я затем приведу RoutedEventArgs.OriginalSource к TextBox и получу текст, подобный этому, не позволяя пользователю покинуть поле, если оно не пусто или не соответствует элементу в списке блока: -

    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();
        }
    }

1 Ответ

1 голос
/ 28 января 2011

Я пытался написать как можно более простой пример. Моя модель наблюдает за изменениями свойства SearchText и обновляет свойства проверки.

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));
    }
}

И xaml:

<sdk:AutoCompleteBox Text="{Binding SearchText, Mode=TwoWay}" />
<Button IsEnabled="{Binding HasErrors, Converter={StaticResource NotConverter}}" Content="Save"/>

Элемент управления имеет красную рамку, и кнопка отключается, если в модели есть ошибки.

...