Silverlight 中的 AutoCompleteBox 和 INotifyDataErrorInfo

发布于 2024-10-14 07:33:30 字数 1795 浏览 1 评论 0原文

有没有人成功应用 INotifyDataErrorInfo 接口并绑定到 AutoCompleteBox。我已经尝试过这个,但没有得到任何回应。该控件不像其他控件那样响应,即带有红色边框和警告工具提示。它还不会使验证摘要控件显示错误。

我已经成功地设置了标准的 TextBoxes 和 DatePickers,它们的行为完美地符合互联网上人们善意提供的许多示例。

如果有一个答案可以保证我的屏幕的一致性,那就太好了,因为我想简单地绑定到 INotifyDataErrorInfo 附带的 HasErrors 属性,以便在准备保存时启用一个按钮,如果没有,我就无法做到这一点额外的代码来检查这些框是否正确。

目前,我通过使用 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();
        }
    }

Has anyone successfully applied the INotifyDataErrorInfo interface and bound to an AutoCompleteBox. I've tried this but I get no response. The control does not respond as other controls i.e. with a red border and a warning tooltip. It also does not make the Validation Summary control display with its error.

I have successfully set up standard TextBoxes and DatePickers and these behave perfectly as per the many examples kindly provided by people on the internet.

it would be good if there was an answer to this for the consistency of my screen, also because i would like to simply bind to the HasErrors property that comes with INotifyDataErrorInfo to enable a button when ready to save and I can't do this without extra code to check that these boxes are correct.

At the moment I treat these differently by using an MVVMLight EventToCommand binding and registering the LostFocus event.

<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>

In the ViewModel I then cast the RoutedEventArgs.OriginalSource to a TextBox and get the text like so, preventing the user from leaving the box unless it is empty or matching an item in the box's list: -

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

当爱已成负担 2024-10-21 07:33:30

我试图写出尽可能简单的例子。
我的模型观察属性 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"/>

该控件有红色边框,当模型出现错误时该按钮被禁用。

I've tried to write as simple example as I can.
My model observe changes of the property SearchText and update validation properties.

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

And xaml:

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

The control has a red border and the button is disabled when the model has errors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文