如何通过tabcontrol tabitem选择更改

时间:2017-07-21 09:14:58

标签: c# wpf prism

在尝试将我的实体保存到数据库之前,我必须验证一些属性。

问题:

  1. Programmstart:tabitem1
  2. 中的文本框显示验证错误
  3. 用户选择:视图中的Tabitem2
  4. 用户选择:视图中的Tabitem1
  5. 空文本框的验证错误不再显示在tabitem1中。
  6. 例行行为:

    如果用户更改了所选的tabitem,则每次都会显示验证错误。

    使用的工具/框架:

    1. Prism 6.3(使用Templatepack PrismUnity的新项目
    2. Prism.Validation(https://github.com/mfe-/Prism.Validation
    3. 问题:

      1. 为什么在不同的tabitems之间选择后不再显示DataAnnoation? ViewModel属性hasErrors为true。
      2. 如果用户再次选择tabitem1,我将如何重新开始评估?
      3. 查看:

        <Window x:Class="PrismUnityApp1TestValidation.Views.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:prism="http://prismlibrary.com/"
                prism:ViewModelLocator.AutoWireViewModel="True"
                Title="{Binding Title}" Height="350" Width="525">
            <StackPanel>
                <!--<ContentControl prism:RegionManager.RegionName="ContentRegion" />-->
                <TabControl>
                <TabItem>
                 <TabItem.Content>
                     <TextBox Height="50" Text="{Binding TestText, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
                 </TabItem.Content>
                </TabItem>
                    <TabItem>
                        <TabItem.Content>
                           <TextBlock Text="TabItem2"></TextBlock>
                        </TabItem.Content>
                    </TabItem>
        
                </TabControl>
            </StackPanel>
        </Window>
        

        视图模型:

        using System.ComponentModel.DataAnnotations;
        using Prism.Mvvm;
        using Prism.Validation;
        
        namespace PrismUnityApp1TestValidation.ViewModels
        {
            public class MainWindowViewModel : ValidatableBindableBase
            {
                private string _title = "Prism Unity Application";
                public string Title
                {
                    get { return _title; }
                    set { SetProperty(ref _title, value); }
                }
        
                private string _testtext;
                [Required]
                public string TestText
                {
                    get { return _testtext; }
                    set { SetProperty(ref _testtext, value); }
                }
        
        
                public MainWindowViewModel()
                {
        
                }
            }
        }
        

        ValidatableBindableBase(NugetPackage Prism.Validation):

        namespace Prism.Validation
        {
            /// <summary>
            /// The IValidatableBindableBase interface was created to add validation support for model classes that contain validation rules.
            /// The default implementation of IValidatableBindableBase is the ValidatableBindableBase class, which contains the logic to run the validation rules of the
            /// instance of a model class and return the results of this validation as a list of properties' errors.
            /// </summary>
            // Documentation on validating user input is at http://go.microsoft.com/fwlink/?LinkID=288817&clcid=0x409
            public class ValidatableBindableBase : BindableBase, IValidatableBindableBase, INotifyDataErrorInfo
            {
                private readonly BindableValidator _bindableValidator;
        
                /// <summary>
                /// Initializes a new instance of the <see cref="ValidatableBindableBase"/> class.
                /// </summary>
                public ValidatableBindableBase()
                {
                    _bindableValidator = new BindableValidator(this);
                }
        
                /// <summary>
                /// Gets or sets a value indicating whether this instance is validation enabled.
                /// </summary>
                /// <value>
                /// <c>true</c> if validation is enabled for this instance; otherwise, <c>false</c>.
                /// </value>
                public bool IsValidationEnabled
                {
                    get { return _bindableValidator.IsValidationEnabled; }
                    set { _bindableValidator.IsValidationEnabled = value; }
                }
        
                /// <summary>
                /// Returns the BindableValidator instance that has an indexer property.
                /// </summary>
                /// <value>
                /// The Bindable Validator Indexer property.
                /// </value>
                public BindableValidator Errors
                {
                    get
                    {
                        return _bindableValidator;
                    }
                }
                /// <summary>
                /// Gets a value that indicates whether the entity has validation errors.
                /// </summary>
                /// <value>
                /// <c>true</c> if this instance contains validation errors; otherwise, <c>false</c>.
                /// </value>
                public bool HasErrors
                {
                    get
                    {
                        return !ValidateProperties();
                    }
                }
        
                /// <summary>
                /// Occurs when the Errors collection changed because new errors were added or old errors were fixed.
                /// </summary>
                public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged
                {
                    add { _bindableValidator.ErrorsChanged += value; }
        
                    remove { _bindableValidator.ErrorsChanged -= value; }
                }
        
                /// <summary>
                /// Gets all errors.
                /// </summary>
                /// <returns> A ReadOnlyDictionary that's key is a property name and the value is a ReadOnlyCollection of the error strings.</returns>
                public ReadOnlyDictionary<string, ReadOnlyCollection<string>> GetAllErrors()
                {
                    return _bindableValidator.GetAllErrors();
                }
        
                /// <summary>
                /// Validates the properties of the current instance.
                /// </summary>
                /// <returns>
                /// Returns <c>true</c> if all properties pass the validation rules; otherwise, false.
                /// </returns>
                public bool ValidateProperties()
                {
                    return _bindableValidator.ValidateProperties();
                }
        
                /// <summary>
                /// Validates a single property with the given name of the current instance.
                /// </summary>
                /// <param name="propertyName">The property to be validated.</param>
                /// <returns>Returns <c>true</c> if the property passes the validation rules; otherwise, false.</returns>
                public bool ValidateProperty(string propertyName)
                {
                    return !_bindableValidator.IsValidationEnabled // don't fail if validation is disabled
                        || _bindableValidator.ValidateProperty(propertyName);
                }
        
                /// <summary>
                /// Sets the error collection of this instance.
                /// </summary>
                /// <param name="entityErrors">The entity errors.</param>
                public void SetAllErrors(IDictionary<string, ReadOnlyCollection<string>> entityErrors)
                {
                    _bindableValidator.SetAllErrors(entityErrors);
                }
        
                /// <summary>
                /// Checks if a property already matches a desired value. Sets the property and
                /// notifies listeners only when necessary. We are overriding this property to ensure that the SetProperty and the ValidateProperty methods are fired in a
                /// deterministic way.
                /// </summary>
                /// <typeparam name="T">Type of the property.</typeparam>
                /// <param name="storage">Reference to a property with both getter and setter.</param>
                /// <param name="value">Desired value for the property.</param>
                /// <param name="propertyName">Name of the property used to notify listeners. This
                /// value is optional and can be provided automatically when invoked from compilers that
                /// support CallerMemberName.</param>
                /// <returns>
                /// True if the value was changed, false if the existing value matched the
                /// desired value.
                /// </returns>
                protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
                {
                    var result = base.SetProperty(ref storage, value, propertyName);
        
                    if (result && !string.IsNullOrEmpty(propertyName))
                    {
                        if (_bindableValidator.IsValidationEnabled)
                        {
                            _bindableValidator.ValidateProperty(propertyName);
                        }
                    }
                    return result;
                }
                /// <summary>
                /// Gets the validation errors for a specified property or for the entire entity.
                /// </summary>
                /// <param name="propertyName">The name of the property to retrieve validation errors for; or null or Empty, to retrieve entity-level errors.</param>
                /// <returns>The validation errors for the property or entity.</returns>
                public IEnumerable GetErrors(string propertyName)
                {
                    if (HasErrors==false)
                    {
                        return Enumerable.Empty<String>();
                    }
                    return _bindableValidator[propertyName];
                }
            }
        }
        

1 个答案:

答案 0 :(得分:0)

我在这里找到了一个解决方案:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb50537c-feec-42dc-8439-dcf78ef8951a/validation-error-and-tab-control?forum=wpf

我改变了帖子我的观点中所提到的。

查看:

<Window x:Class="PrismUnityApp1TestValidation.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
    <StackPanel>
        <!--<ContentControl prism:RegionManager.RegionName="ContentRegion" />-->
        <TabControl>
        <TabItem IsSelected="{Binding TabItem1Selected}">
         <TabItem.Content>
             <AdornerDecorator>
                 <TextBox Height="50" Text="{Binding TestText, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
                    </AdornerDecorator>

         </TabItem.Content>
        </TabItem>
            <TabItem>
                <TabItem.Content>
                   <TextBlock Text="TabItem2"></TextBlock>
                </TabItem.Content>
            </TabItem>

        </TabControl>
    </StackPanel>
</Window>