2

我有一个相当简单的视图,它用作搜索表单。有两个组合框和一个带有“搜索”按钮的文本框。如果下拉列表中没有选择或文本框为空,则无法执行搜索。我在我的应用程序的几个地方使用了 IDataErrorInfo,但它似乎不适合这里(我没有“SearchPageModel”,我不确定如何在视图模型上实现它),并且由于完全缺乏验证器控制,我不知道该怎么做。如果用户尝试搜索而之前没有这样做,我只想显示一条有关填写所有信息的消息。最简单的方法是什么?

更新: 按照第一个答案的链接中的建议,我创建了一个验证规则并将我的文本框修改为如下所示:

    <TextBox Grid.Column="1" Grid.Row="3" Name="tbxPartNumber" Margin="6">
        <TextBox.Text>
            <Binding Path="SelectedPartNumber" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <local:RequiredTextValidation/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

但是,这里有一个新问题:当我转到屏幕并在文本框中输入内容然后删除它时,该框按预期以红色突出显示。Validation.GetHasErrors(tbxPartNumber) 返回真。如果我进入屏幕并且根本不与文本框交互,则 Validation.GetHasErrors(tbxPartNumber) 返回 false。它似乎只在我修改文本时才有效......它不会验证用户是否只是出现并单击搜索而不输入任何内容。有没有解决的办法?

4

1 回答 1

2

MSDN 上的这篇文章提供了一个很好的示例,说明如何验证此类内容,请查看相应的小节(“验证用户提供的数据”)。关键是使用ValidationRules并检查对话框的整个逻辑树是否有错误。

编辑: ValidationRule 上的设置应该在这里解决问题。事实上,该属性的 MSDN 文档中的示例正是这种情况。此外,在这种情况下,这个答案可能会引起人们的兴趣。ValidatesOnTargetUpdated="True"

Edit2:这是我拥有的导致验证失败的完整代码:

<Window x:Class="Test.Dialogs.SearchDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:diag="clr-namespace:Test.Dialogs"
        xmlns:m="clr-namespace:HB.Xaml"
        Title="Search" SizeToContent="WidthAndHeight" ResizeMode="NoResize"
        Name="Window" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <Grid.Resources>
            <Style x:Key="BaseStyle" TargetType="{x:Type FrameworkElement}">
                <Setter Property="Margin" Value="3"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseStyle}"/>
            <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseStyle}"/>
            <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}"/>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseStyle}"/>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.Children>
            <TextBlock Grid.Column="0" Grid.Row="0" Text="Scope:"/>
            <ComboBox Grid.Column="1" Grid.Row="0" ItemsSource="{m:EnumItems {x:Type diag:SearchDialog+ScopeMode}}">
                <ComboBox.SelectedItem>
                    <Binding Path="Scope">
                        <Binding.ValidationRules>
                            <diag:HasSelectionValidationRule />
                        </Binding.ValidationRules>
                    </Binding>
                </ComboBox.SelectedItem>
            </ComboBox>

            <TextBlock Grid.Column="0" Grid.Row="1" Text="Direction:"/>
            <ComboBox Grid.Column="1" Grid.Row="1" ItemsSource="{m:EnumItems {x:Type diag:SearchDialog+DirectionMode}}">
                <ComboBox.SelectedItem>
                    <Binding Path="Direction">
                        <Binding.ValidationRules>
                            <diag:HasSelectionValidationRule />
                        </Binding.ValidationRules>
                    </Binding>
                </ComboBox.SelectedItem>
            </ComboBox>


            <TextBlock Grid.Column="0" Grid.Row="2" Text="Expression:"/>
            <TextBox Name="tb" Grid.Column="1" Grid.Row="2">
                <TextBox.Text>
                    <Binding Path="Expression" UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <diag:StringNotEmptyValidationRule />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>

            <Button Grid.Column="1" Grid.Row="3" Content="Search" Click="Search_Click"/> 
        </Grid.Children>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Test.Dialogs
{
    /// <summary>
    /// Interaction logic for SearchDialog.xaml
    /// </summary>
    public partial class SearchDialog : Window
    {
        public enum ScopeMode { Selection, Document, Solution }
        public enum DirectionMode { Up, Down }

        public ScopeMode Scope { get; set; }
        public DirectionMode Direction { get; set; }
        private string _expression = String.Empty;
        public string Expression
        {
            get { return _expression; }
            set { _expression = value; }
        }


        public SearchDialog()
        {
            InitializeComponent();
        }

        private void Search_Click(object sender, RoutedEventArgs e)
        {
            (sender as Button).Focus();
            if (IsValid(this)) MessageBox.Show("<Searching>");
            else MessageBox.Show("Errors!");
        }

        bool IsValid(DependencyObject node)
        {
            if (node != null)
            {
                bool isValid = Validation.GetHasError(node);
                if (!isValid)
                {
                    if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                    return false;
                }
            }
            foreach (object subnode in LogicalTreeHelper.GetChildren(node))
            {
                if (subnode is DependencyObject)
                {
                    if (IsValid((DependencyObject)subnode) == false) return false;
                }
            }
            return true;
        }
    }

    public class HasSelectionValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (value == null)
            {
                return new ValidationResult(false, "An item needs to be selected.");
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }

    public class StringNotEmptyValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            if (String.IsNullOrWhiteSpace(value as string))
            {
                return new ValidationResult(false, "The search expression is empty.");
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }
}
于 2011-05-16T13:43:46.400 回答