【问题标题】:WPF DataBinding watch for thrown exceptionsWPF DataBinding 监视抛出的异常
【发布时间】:2010-12-13 11:26:18
【问题描述】:

在我的模型中,我有很多不同对象的属性,我在为对象设置值时检查值,如果不接受该值,我将抛出异常,这与 Windows 窗体 propertygrid 完美配合,但现在我'我尝试使用 WPF 设计一个新界面。 在 WPF 中,当我将属性绑定到文本框之类的控件时,当值更改时,我不知道如何处理异常并显示错误消息。 示例:

public string  ConnectionString
        {
            get
            {
                return (_ConnectionString);
            }
            set
            {
                try
                {
                    _ConnectionString  = value ;
                    _SqlConnection = new System.Data.SqlClient.SqlConnection(_ConnectionString);
                    _ConnectionTested = true;
                }
                catch (Exception caught)
                {
                    _ConnectionTested = false;
                    _TableNameTested = false;
                    _FieldNameTested = false;
                    _ConditionTested = false;
                    _ConnectionString = "";
                    //----delete values----
                    ValuesCollection.Clear();
                    throw (new Exception("Can not Open the connection String \nReason : " + caught.Message )); 
                }
            }
        }

wpf 部分是这样的:

<TextBox TextWrapping="Wrap" x:Name="ConnectionStringTextBox" Text="{Binding Path=ConnectionString, Mode=TwoWay}"/>

当文本框中的值发生变化时,检查模型是否抛出异常,然后向用户显示 exception.message 吗?

谢谢

【问题讨论】:

    标签: c# wpf data-binding exception-handling


    【解决方案1】:

    Kent 关于使用 ValidationRule 和 ExceptionValidationRule 是绝对正确的。但是,您会发现此解决方案非常不适合您对此类字段有大量绑定的情况。在许多地方,您将替换如下内容:

    <TextBox Text="{Binding Value}" />
    

    用这个:

    <TextBox Validation.ErrorTemplate="{StaticResource errorTemplate}">
      <TextBox.Text>
        <Binding Path="Value">
          <Binding.ValidationRules>
            <ExceptionValidationRule />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
    

    因为这太笨拙了,所以我喜欢创建一个继承的附加属性,它会自动应用验证规则,所以我要说的是:

    <Window
      ValidationHelper.ErrorTemplate="{StaticResource errorTemplate}"
    ...
       <TextBox Text="{Binding Value}" />
       <TextBox Text="{Binding OtherValue}" />
    

    我的附加属性会自动将验证应用于窗口中的每个绑定,因此各个文本框不必担心验证。

    为此,我使用以下通用技术:

      public class ValidationHelper : DependencyObject
      {
        [ThreadStatic]
        static List<DependencyObject> _objectsNeedingValidationUpdate;
    
        public static ControlTemplate GetErrorTemplate(DependencyObject obj) { return (ControlTemplate)obj.GetValue(ErrorTemplateProperty); }
        public static void SetErrorTemplate(DependencyObject obj, ControlTemplate value) { obj.SetValue(ErrorTemplateProperty, value); }
        public static readonly DependencyProperty ErrorTemplateProperty = DependencyProperty.RegisterAttached("ErrorTemplate", typeof(ControlTemplate), typeof(ValidationHelper), new FrameworkPropertyMetadata
        {
          Inherits = true,
          PropertyChangedCallback = (obj, e) =>
            {
              if(e.NewValue)
                if(_objectsNeedingValidationUpdate!=null)
                  _objectsNeedingValidationUpdate.Add(obj);
                else
                {
                  _objectsNeedingValidationUpdate = new List<DependencyObject>();
                  _objectsNeedingValidationUpdate.Add(obj);
                  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new Action(UpdateValidations));
                }
            },
        });
    
        static void UpdateValidations()
        {
          List<DependencyObject> objects = _objectsNeedingValidationUpdate;
          _objectsNeedingValidationUpdate = null;
          if(objects!=null)
            foreach(DependencyObject obj in objects)
              UpdateValidations(obj);
        }
        static void UpdateValidations(DependencyObject obj)
        {
          // My regular code uses obj.GetLocalValueEnumerator here, but that would require some other complexity
          if(UpdateValidations(obj, TextBox.TextProperty))
            if(Validation.GetErrorTemplate(obj)==null)
              Validation.SetErrorTemplate(obj, ValidationHelper.GetErrorTemplate(obj));
        }
        static bool UpdateValidations(DependencyObject obj, DependencyProperty prop)
        {
          var binding = BindingOperations.GetBinding(obj, prop);
          if(binding!=null &&
            binding.Mode==BindingMode.TwoWay &&
            !binding.ValidationRules.Any(rule => rule is ExceptionValidationRule))
          {
            binding.ValidationRules.Add(new ExceptionValidationRule());
            BindingOperations.SetBinding(obj, prop, binding);  // Required to get new rule to work
            return true;
          }
          return false;
        }
      }
    

    有关如何创建 errorTemplate 资源的示例,请参阅 Validation 类的 MSDN 文档。另请注意:

    • 我的 ValidationHelper 类不会阻止您设置自定义 Validation.ErrorTemplate 值 单个文本框。这些将覆盖 ValidationHelper.ErrorTemplate。
    • 您可以轻松添加对 TextBox 以外的控件和 Text 以外的属性的支持

    【讨论】:

    • 你是唯一一个明白一行代码被强制变成9行代码有多丑的人。
    【解决方案2】:

    看看binding validationBinding 类有一个 ValidationRules 集合,您可以向其中添加一个 ExceptionValidationRule

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多