【问题标题】:WPF error template not showingWPF 错误模板未显示
【发布时间】:2010-10-19 22:02:52
【问题描述】:

我没有收到任何绑定错误,并且此代码在其他地方也可以使用。我还没有发现我现在所做的与它工作的代码有什么不同,而且代码不多。

UserControl.Resource:

<Style TargetType="TextBox">
  <Setter Property="BorderBrush" Value="DarkBlue"/>
  <Setter Property="BorderThickness" Value="1"/>
  <Setter Property="Margin" Value="0,1,0,1"/>
  <Setter Property="Validation.ErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <StackPanel Orientation="Horizontal">
          <AdornedElementPlaceholder/>
          <Grid Margin="2,0,0,0">
            <Ellipse Width="20" Height="20" Fill="Red"/>
            <TextBlock Foreground="White" Text="X" FontWeight="Bold"
                       HorizontalAlignment="Center" VerticalAlignment="Center"/>
          </Grid>
        </StackPanel>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="True">
      <Setter Property="ToolTip"
              Value="{Binding RelativeSource={RelativeSource Self},
                  Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </Style.Triggers>
</Style>

在 Xaml 中也是如此:

<TextBlock Height="23" HorizontalAlignment="Left" Margin="22,90,0,0"
           Text="Keywords" VerticalAlignment="Top"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="22,108,0,0"
         VerticalAlignment="Top" Width="244">
  <Binding Path="Tags" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
    <Binding.ValidationRules>
      <DataErrorValidationRule ValidatesOnTargetUpdated="False"/>
    </Binding.ValidationRules>
  </Binding>
</TextBox>

仅当Model.Tags 属性超过用户输入的 10 个字符时,我的 ViewModel 中的按钮 SAVE 才会被激活。当我输入 10,11 然后返回 8 个字符时,按钮激活/禁用工作正常。触发所有属性更改。

型号

namespace TBM.Model
{
    public class Document : EntityBase , IDataErrorInfo
    {
        public int Id { get; set; }
        public string DocumentName { get; set; }
        public string Tags { get; set; }
        public byte[] DocumentData { get; set; }
        public int PeriodId { get; set; }

        string IDataErrorInfo.Error { get { return null; } }

        string IDataErrorInfo.this[string propertyName]
        {
            get { return this.GetValidationError(propertyName); }
        }

        public bool IsValid
        {
            get
            {
                foreach (string property in ValidatedProperties)
                    if (GetValidationError(property) != null)
                        return false;

                return true;
            }
        }

        static readonly string[] ValidatedProperties = { "Tags", };

        private string GetValidationError(string propertyName)
        {
            if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
                return null;

            string error = null;

            switch (propertyName)
            {               
                case "Tags": error = this.IsTagsEmpty(Tags); break;

                default:
                    Debug.Fail("Unexpected property being validated on Document: " + propertyName);
                    break;
            }
            return error;
        }  

        private string IsTagsEmpty(string value)
        {
            if (value != null && value.Trim().Length >= 10)
                return null;
            else
               return "The keywords must have at least 10 chars!";            
        }
    }
}

视图模型

 public RelayCommand SaveDocumentCommand
 {
     get { return _saveDocumentCommand ?? (_saveDocumentCommand =
         new RelayCommand(() => SaveDocument(),() => CanSaveDocument())); }
     }

     private bool CanSaveDocument()
     {
         return _document.IsValid;
     }
//...

什么不起作用是带有红色椭圆的 ErrorTemplate 根本没有显示?

更新:下面的代码完全可以在 TEST 项目中使用。但是在我的生产项目中它没有找到资源???为什么会这样?

<TextBlock Height="23" HorizontalAlignment="Left" Margin="22,89,0,0"
           Text="Keywords" VerticalAlignment="Top"/>
  <TextBox Style="{StaticResource bla}" Height="23" HorizontalAlignment="Left"
           Margin="22,109,0,0" VerticalAlignment="Top" Width="244">
    <Binding Path="Tags" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <DataErrorValidationRule ValidatesOnTargetUpdated="False"
                                 ValidationStep="UpdatedValue"/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox>

<UserControl.Resources>
  <Style x:Name="bla" TargetType="TextBox">
    <Setter Property="BorderBrush" Value="DarkBlue"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Margin" Value="0,1,0,1"/>
    <Setter Property="Validation.ErrorTemplate">
      <Setter.Value>
        <ControlTemplate>
          <StackPanel Orientation="Horizontal">                          
            <AdornedElementPlaceholder/>
            <Grid Margin="2,0,0,0">
              <Ellipse Width="20" Height="20" Fill="Red"/>
              <TextBlock Foreground="White" Text="X" FontWeight="Bold"
                         HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Grid>
          </StackPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Style.Triggers>
      <Trigger Property="Validation.HasError" Value="True">
        <Setter Property="ToolTip"
                Value="{Binding RelativeSource={RelativeSource Self},
                    Path=(Validation.Errors)[0].ErrorContent}"/>
      </Trigger>
    </Style.Triggers>
  </Style>
</UserControl.Resources>

【问题讨论】:

    标签: wpf xaml templates mvvm idataerrorinfo


    【解决方案1】:

    我有类似的问题。打了几个小时才意识到装饰层出了点问题。

    我所做的是将我的 with 控件放入 .就是这样。由于某种原因,这个装饰层有时会消失。这对于 TabControl 来说当然是正确的(但在我的情况下是其他原因)。

    所以它应该是这样的

    <AdornerDecorator>
      <Grid>
        <TextBox .../>
      </Grid>
    </AdornerDecorator>
    

    希望这会有所帮助!

    【讨论】:

    • 这正是我所需要的。在选项卡控件中的选项卡之间来回切换时显示的错误模板出现问题。一旦我添加了 AdornerDecorator,它就会在我每次切换到选项卡时始终显示。谢谢!
    • 谢谢,这也是我的问题。这个答案提供了更多见解 [link]stackoverflow.com/a/2597006/1477247
    • 谢谢 - 我的问题是主题的变体 - 当我在窗口内的嵌入式用户控件之间切换时,我的错误模板根本没有显示。在嵌入式用户控件的顶层添加“AdornerDecorator”修复了它。
    【解决方案2】:

    我遇到了类似的问题,结果不是模板,但验证没有返回我预期的结果。

    【讨论】:

    • 验证总是返回我期望的值。因此按钮被启用/禁用。
    • 我将您的代码放入用户控件中,并将 IsEnabled 属性绑定到 IsValid 并且一切正常。您是否尝试过在 UI 上运行 snoop 以确保您没有与椭圆重叠的东西。是否有另一种 TextBox 样式覆盖?尝试将代码从您的项目中取出并放入测试应用程序中,并确保它在那里工作。
    • 是的,我仍然想在一个额外的项目中单独测试它。虽然我在左侧仍有大约 30 像素的空间,但它不可见......该死的可能是边距......稍后再检查。 Ooooh snoop 不喜欢它通常无法按预期工作......事实上没有其他文本框隐式样式或显式样式。稍后我会告诉你...
    • 一切正常?究竟是什么工作?当按钮被禁用时,您是否看到红色错误省略号?
    • 不想这么说,但您的 Xaml 看起来和 IDataErrorInfo 实现一样好。这一切都奏效了,这就是为什么我建议使用 snoop 检查最终输出,使控件进入错误状态,然后在可视树中找到椭圆
    【解决方案3】:

    ViewModel 必须实现 IDataErrorInfo,而不是 Model。 ViewModel 作为 DataContext 而不是 Model 绑定到您的 View,因此在 ViewModel 中实现接口并绑定到 XAML 中的相应属性。

    【讨论】:

    • 这是有争议的...... Josh Smith mvvm 文章将验证放在模型中,当您通过服务导出模型时,更倾向于将模型及其验证放在一起,但就我而言,是的,我会改变那可能。尽管我必须说您的解决方案与我的问题无关;-)您应该对此发表评论。
    猜你喜欢
    • 1970-01-01
    • 2011-04-10
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 2013-11-24
    相关资源
    最近更新 更多