WPF可编辑组合框验证

时间:2013-04-11 20:09:55

标签: wpf validation mvvm

我想要完成的是能够验证输入到可编辑组合框中的新类别,或者从现有的组合框列表中选择一个。

验证仅适用于selectedItem,不适用于输入Text的新文本。只要我将ValidateOnDataErrors="True"添加到ComboBox'es Text属性,就不会触发输入新文本的事件。 Category是一个带有Id和Name的简单对象。

XAML:

<Window.Resources>
    <ControlTemplate x:Key="ValidationErrorTamplate">
        <Border BorderBrush="DodgerBlue" BorderThickness="0.75">
            <AdornedElementPlaceholder />
        </Border>
    </ControlTemplate>
    <Style x:Key="ElementInError" TargetType="{x:Type FrameworkElement}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<ComboBox Name="CbCategory"
          DisplayMemberPath="Name"
          IsEditable="True"
          ItemsSource="{Binding Categories}"
          SelectedItem="{Binding SelectedCategory,
                                 UpdateSourceTrigger=PropertyChanged,
                                 ValidatesOnDataErrors=True}"
          Style="{StaticResource ElementInError}"
          Text="{Binding NewCategory.Name,
                         UpdateSourceTrigger=PropertyChanged,
                         ValidatesOnDataErrors=True}"
          Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate}" />

ViewModel:(: IDataErrorInfo

    private Category _newCategory;
    private Category _selectedCategory;

    public ExpenseCategory SelectedCategory
    {
       get { return _selectedCategory; }
       set
           {
              if (Equals(_selectedCategory, value)) return;
              _selectedCategory = value;
              SendPropertyChanged("SelectedCategory");
            }
     }
     public ExpenseCategory NewExpenseCategory
     {
        get { return _newExpenseCategory ?? (_newExpenseCategory = new ExpenseCategory()); }
            set
            {
                if (Equals(_newExpenseCategory, value)) return;
                _newExpenseCategory = value;
                SendPropertyChanged("NewExpenseCategory");
            }
        }

public string this[string propertyName]
        {
            get
            {
                switch (propertyName)
                {
                    case "SelectedExpenseCategory":
                    case "NewExpenseCategory":
                        {
                            if ((SelectedCategory == null) || (NewCategory == null)
                            {
                                return "Category must be selected or entered";
                            }
                        }
                        break;
                }
                return string.Empty;
            }

1 个答案:

答案 0 :(得分:1)

让它工作,它可能不是一流的方式,但它完成了工作。

我基本上做了什么,我将NewCategory更改为字符串,而不是Category类型的对象。当用户将新值填充到组合框中时,它会根据传递给NewCategory构造函数的值启动新的SelectedCategory。如果我保留对象类型Category的NewCategory,它就不起作用。

   public string NewExpenseCategory
    {
        get { return _newExpenseCategory ?? (_newExpenseCategory = ""); }
        set
        {
            if (Equals(_newExpenseCategory, value)) 
                return;
            _newExpenseCategory = value;
            SendPropertyChanged("NewExpenseCategory");
            SelectedExpenseCategory = new ExpenseCategory
                {
                    Name = value
                };
        }
    }

    public string this[string propertyName]
    {
        get
        {
            switch (propertyName)
            {
                case "SelectedExpenseCategory":
                case "NewExpenseCategory":
                    {
                        if ((SelectedExpenseCategory.Name.Length == 0) && (NewExpenseCategory.Length == 0))
                        {
                            return "Category must be selected or entered";
                        }
                    }
                    break;
            }
            return string.Empty;
        }
    }