WPF错误模板未显示

4

我没有遇到绑定错误,这段代码在其他地方可以运行。我还没有找出我现在做了什么不同于它可以正常工作的代码,而且代码量也不是很大。

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中的保存按钮才会被激活。当我输入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!";            
        }
    }
}

ViewModel:

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

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

错误模板中的红色椭圆不显示,这是不起作用的。

更新: 在测试项目中确切的下面代码可以工作。但在我的生产项目中找不到资源?为什么会这样?

<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>
3个回答

13

我曾经遇到过类似的问题。我为此奋斗了几个小时,直到意识到adorner层出了问题。

我的解决方法是将我的``和其中的控件包含在一起。这就行了。由于某种原因,这个装饰层有时会消失。这对于TabControl来说肯定是正确的(但在我的情况下是其他原因)。

所以它应该看起来像这样:

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

希望这能帮到你!


2
这正是我所需要的。在选项卡控件中来回切换时,错误模板显示有问题。一旦我添加了AdornerDecorator,每次切换到选项卡时它都可以正确地显示。谢谢! - Geo242
谢谢,那也是我的问题。这个答案提供了更多的见解 [链接]https://dev59.com/SHM_5IYBdhLWcg3wNgOZ#2597006 - Daniel
谢谢 - 我的问题是一个变体 - 当我在窗口内切换嵌入式用户控件时,我的错误模板根本没有显示。在嵌入式用户控件的顶层添加 'AdornerDecorator' 解决了这个问题。 - Wolfshead

0

我曾经遇到过类似的问题,结果发现不是模板的问题,而是验证没有返回我期望的结果。


验证始终返回我期望的值。因此按钮被启用/禁用。 - Elisabeth
我将您的代码放入了一个用户控件中,并将IsEnabled属性绑定到IsValid,一切都完美地运行了。您是否尝试在UI上运行Snoop以确保没有东西重叠椭圆形?可能有另一个TextBox样式覆盖了它吗?请尝试将代码从您的项目中取出并放入测试应用程序中,确保它在那里正常工作。 - benPearce
是的,我仍然想在一个额外的项目中进行隔离测试。虽然左侧还有大约30像素的空间,但它不可见...该死,也许是边距...稍后再检查。哦,糟糕,Snoop不喜欢它,经常不能按预期工作...据我所知,没有其他文本框隐式样式或显式样式。稍后我会告诉你... - Elisabeth
所有的都运行得很完美吗?具体是什么在运行?当按钮被禁用时,你是否看到了红色的错误圆圈? - Elisabeth
不想说,但你的Xaml看起来很好,IDataErrorInfo实现也没问题。一切都正常工作,这就是我建议使用Snoop检查最终输出,将控件置于错误状态,然后在Visual树中找到椭圆形的原因。 - benPearce
显示剩余4条评论

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

3
这是值得商榷的…… Josh Smith的mvvm文章将验证放在模型中,而且更重要的是,当通过服务导出模型时,将模型及其验证放在一起是首选的。但在我的情况下,我可能会改变这种做法。虽然我必须说,你的解决方案与我的问题无关 ;-) 你应该对此进行评论。 - Elisabeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接