2

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

验证仅适用于 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}" />

视图模型:( : 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;
            }
4

1 回答 1

1

得到它的工作,它可能不是最好的方法,但它可以完成工作。

我基本上做了什么,我将 NewCategory 更改为字符串,而不是 Category 类型的对象。当用户将新值填充到组合框中时,它会根据传递给 NewCategory 构造函数的值启动一个新的 SelectedCategory。如果我保留对象类型类别的 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;
        }
    }
于 2013-04-12T20:29:41.950 回答