4

我有 2 个文本框,1 个用于最小值,另一个用于最大值。他们不能互相调用 propertychange 事件,因为这会破坏其他一些功能。我的视图模型上有一个 IDataErrorInfo 接口,当一个文本框被验证时,另一个文本框也需要被验证。

例如,我正在寻找的验证是当最小值大于最大值时需要出现错误,但是可以从任一文本框中更正此错误,并且在发生这种情况时需要删除文本框的错误。这很容易通过让 min 和 max 属性调用彼此的属性更改事件来实现,但我不能这样做,因为它会破坏其他功能。我需要另一种方式。有任何想法吗?

     #region Implementation of IDataErrorInfo

            /// <summary>
            /// Gets the error message for the property with the given name.
            /// </summary>
            /// <returns>
            /// The error message for the property. The default is an empty string ("").
            /// </returns>
            /// <param name="columnName">The name of the property whose error message to get. </param>
            public string this[string columnName]
            {
                get
                {
                    string error = null;
                    if (columnName == Reflection.GetPropertyName<ColorPaletteManagerViewModel>(m => m.MaximumColorValue) ||
                        columnName == Reflection.GetPropertyName<ColorPaletteManagerViewModel>(m => m.MinimumColorValue))
                    {
                        error = GetTimeGateError();
                    }
                    _errors[columnName] = error;                              
                    OnPropertyChanged<ColorPaletteManagerViewModel>(m => m.Error);
                    return error;
                }
            }

            /// <summary>
            /// Gets an error message indicating what is wrong with this object.
            /// </summary>
            /// <returns>
            /// An error message indicating what is wrong with this object. The default is an empty string ("").
            /// </returns>
            public string Error
            {
                get
                {
                    string[] allErrors =
                        _errors.Where(i => !string.IsNullOrWhiteSpace(i.Value)).Select(m => m.Value).ToArray();
                    return string.Join(Environment.NewLine, allErrors);
                }
            }


            #endregion

    private string GetTimeGateError()
            {
                string error = null;

                if (MinimumColorValue > MaximumColorValue)
                {
                    error = string.Format("The Maximum Color Range Cannot be Less Then The Minimum Color Range");
                }

                return error;
            }

 /// <summary>
        /// Gets or sets the maximum color value.
        /// </summary>
        public float MaximumColorValue
        {
            get { return _maximumColorValue; } 
            set
            {
                if (_maximumColorValue != value)
                {
                    _maximumColorValue = value;
                    OnPropertyChanged(i => i.MaximumColorValue);
                }
            }
        }

        /// <summary>
        /// Gets or sets the minimum color value.
        /// </summary>
        public float MinimumColorValue
        {
            get { return _minimumColorValue; }
            set
            {
                if (_minimumColorValue != value)
                {
                    _minimumColorValue = value;
                    OnPropertyChanged(i => i.MinimumColorValue);
                }
            }
        }

xml:

 <UserControl.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                            Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
            </Style>
    </UserControl.Resources>

     <TextBox Name="_minColorValue" 
                         Width="55" 
                         Height="22"
                         Grid.Row="1" 
                         Grid.Column="1" 
                         Margin="0,-4,0,0"
                         IsEnabled="{Binding ElementName=_override, Path=IsChecked}">
                    <TextBox.Text>
                        <Binding Path="MinimumColorValue" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Delay="500">
                            <Binding.ValidationRules>
                                <ValidationRules:NumberValidationRule/>
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>

     <TextBox Name="_maxColorValue"
                         Width="55" 
                         Height="22"
                         Margin="0,-4,0,0"
                         HorizontalAlignment="Left" 
                         IsEnabled="{Binding ElementName=_override, Path=IsChecked}"
                         Grid.Column="1" 
                         Grid.Row="2">
                    <TextBox.Text>
                        <Binding Path="MaximumColorValue" ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged" Delay="500">
                            <Binding.ValidationRules>
                                <ValidationRules:NumberValidationRule/>
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>
4

2 回答 2

4

如果您的目标是 .NET 4.5,则可以改用该INotifyDataErrorInfo接口。这个接口几乎是更好的版本,IDataErrorInfo它包含一个ErrorsChanged事件,告诉 WPF 重新评估给定属性或所有属性的错误。然后,您可以根据需要简单地引发此事件。

不幸的是,这个接口只在 .NET 4.5 之后才可用,所以希望它对您可用。

于 2013-11-13T23:23:56.830 回答
1

我建议您使用附加属性来解决这个问题。

创建一个 TextBox 类型的附加属性。

将该附加属性放在第一个 TextBox 上,并使用 x:Reference 或 Binding ElementName 将其值设置为第二个 TextBox 的值。

将相同的附加属性放在另一个 TextBox 上,只是这次将其值设置为第一个 TextBox 的引用。

现在每个 TextBox 都知道另一个。那是你赢了。

现在您需要做的只是在一个文本框更新源或文本输入或其他任何内容时使另一个文本框无效或更改。

你现在可以和他们一起做任何你想做的事情,因为他们总是会知道另一个人。

这个建议怎么样?我希望我可以发表评论,但它不适合。

于 2013-11-13T23:05:21.557 回答