ErrorTemplate 显示用户控件而不是其中的文本框!怎么修?

Posted

技术标签:

【中文标题】ErrorTemplate 显示用户控件而不是其中的文本框!怎么修?【英文标题】:ErrorTemplate showing for the user control and not the text box within it! How to fix? 【发布时间】:2013-09-14 16:19:20 【问题描述】:

这里有与此类似的问题,但是我尝试了上述解决方案无济于事!

让我简单介绍一下设置 - 我有一个实现 IDataErrorInfo 的模型,一个将模型公开给视图的视图模型,在视图中我有一个用户控件,它只是一个带标签的文本框,模型属性绑定到用户控件的内部文本框通过依赖属性......并且一切都正确绑定,所有验证都被触发并返回正确的错误!但是,用户控件似乎正在拦截错误,因此显示的是用户控件的错误模板,而不是文本框。

所以,我知道我可以通过将属性设置为 x:Null 来阻止显示用户控件的错误模板,但是如何触发显示文本框的错误模板?!我已经尝试在用户控件中实现 IDataErrorInfo(如某些人所建议的那样)并在用户控件中明确定义验证错误模板,但我就是无法显示该死的东西。在这一点上,我认为用户控件只是拦截错误,抓住它而不将它传递到文本框,因此错误模板没有显示,因为它不知道错误。

过去一天我一直在拔头发,真的不想求助于不使用用户控件,因为我知道这可以实现,但我真的不知道如何解决它!因此,如果有任何巫师可以提供帮助,我将非常感激!

用户控件 XAML:

<UserControl x:Class="PIRS_Client.Control.LabelTextBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" Height="40.541" Width="321.027">
<Grid Height="41" VerticalAlignment="Top" HorizontalAlignment="Left" Width="321">        
    <StackPanel Orientation="Horizontal" Margin="0,8,50,9">
    <Label Content="Label" Height="28" Name="BaseLabel" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="116" FontSize="11" />
        <TextBox Height="22" Width="100" Margin="0,0,0,0" x:Name="BaseTextBox" VerticalContentAlignment="Center" VerticalAlignment="Top" FontSize="11"/>
    </StackPanel>
</Grid>

用户控制代码:

public partial class LabelTextBox : UserControl


    public static readonly DependencyProperty TextBoxTextProperty = DependencyProperty.Register("TextBoxText", typeof(string), typeof(LabelTextBox), new FrameworkPropertyMetadata()  BindsTwoWayByDefault = true );

    public LabelTextBox()
    
        InitializeComponent();

        Binding textBoxText = new Binding("TextBoxText")  Source = this, Mode = BindingMode.TwoWay ;
        BaseTextBox.SetBinding(TextBox.TextProperty, textBoxText);
            

    [Browsable(true)]
    public string LabelText
    
        get  return BaseLabel.Content.ToString(); 
        set
        
            BaseLabel.Content = value;
        
    

    [Browsable(true)]
    public string TextBoxText
    
        get  return (string)GetValue(TextBoxTextProperty); 
        set  SetValue(TextBoxTextProperty, value); 
    

    [Browsable(true)]
    public double TextBoxWidth
    
        get  return BaseTextBox.Width; 
        set
        
            BaseTextBox.Width = value;
        
    

查看 - 用户控件声明:

        <control:LabelTextBox HorizontalAlignment="Left" LabelText="Email" TextBoxText="Binding UpdateSourceTrigger=LostFocus, Path=NewFosterCarerInfo.partner_email, ValidatesOnDataErrors=true, NotifyOnValidationError=true" TextBoxWidth="120" Margin="190,182,-61,0" VerticalAlignment="Top" Height="41" Width="321"/>

【问题讨论】:

您可以尝试通过子类化TextBox来创建自定义控件,而不是创建用户控件 在你的用户控件中设置文本框绑定时也设置ValidatesOnDataErrors=true @Shoe 我已经设置了 ValidatesOnDataErrors=true... 我希望那是我错过的,并且修复是那么简单!不过谢谢! 我在 &lt;control:LabelTextBox.. 的用法上看到了 ValidatesOnDataErrors=true,但在控件本身的 xaml 定义或代码隐藏中没有看到 @Shoe 我怎么把它放在那里?除了在用户控件本身中声明文本绑定......这显然没有意义......对吧?! 【参考方案1】:

对于任何有我问题的人,这里是工作代码

用户控件 xaml:

<UserControl x:Class="PIRS_Client.Control.LabelTextBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" Height="40.541" Width="321.027"             
         x:Name="Parent" Validation.ErrorTemplate="x:Null">

<Grid Height="41" VerticalAlignment="Top" HorizontalAlignment="Left" Width="321" DataContext="Binding ElementName=Parent, ValidatesOnDataErrors=True">
    <StackPanel Orientation="Horizontal" Margin="0,8,50,9">
        <Label Content="Label" Height="28" Name="BaseLabel" VerticalAlignment="Top" HorizontalContentAlignment="Right" Width="116" FontSize="11" />
        <TextBox Height="22" Text="Binding Path=TextBoxText, ValidatesOnDataErrors=True" Width="100" Margin="0,0,0,0" x:Name="BaseTextBox" VerticalContentAlignment="Center" VerticalAlignment="Top" FontSize="11"/>
    </StackPanel>
</Grid>

UserControl 后面的代码:

public partial class LabelTextBox : UserControl, IDataErrorInfo
       
    public LabelTextBox()
    
        InitializeComponent();
    

    public static readonly DependencyProperty TextBoxTextProperty =
        DependencyProperty.Register(
            "TextBoxText",
            typeof(string),
            typeof(LabelTextBox),
            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
    );

    #region IDataErrorInfo Members

    public string Error
    
        get
        
            if (Validation.GetHasError(this))
                return string.Join(Environment.NewLine, Validation.GetErrors(this).Select(e => e.ErrorContent));

            return null;
        
    

    public string this[string columnName]
    
        get
        
            // use a specific validation or ask for UserControl Validation Error 
            if (Validation.GetHasError(this))
            
                var error = Validation.GetErrors(this).FirstOrDefault(e => ((BindingExpression)e.BindingInError).TargetProperty.Name == columnName);
                if (error != null)
                    return error.ErrorContent as string;
            

            return null;
        
    

    #endregion

    [Browsable(true)]
    public string LabelText
    
        get  return BaseLabel.Content.ToString(); 
        set  BaseLabel.Content = value; 
    

    [Browsable(true)]
    public string TextBoxText
    
        get  return (string)GetValue(TextBoxTextProperty); 
        set  
            SetValue(TextBoxTextProperty, value);
        
    

    [Browsable(true)]
    public double TextBoxWidth
    
        get  return BaseTextBox.Width; 
        set  BaseTextBox.Width = value; 
    

使用用户控件:

            <control:LabelTextBox HorizontalAlignment="Left" LabelText="Email" TextBoxText="Binding Path=NewFosterCarerInfo.partner_email, ValidatesOnDataErrors=true" TextBoxWidth="120" Margin="190,182,-61,0" VerticalAlignment="Top" Height="41" Width="321"/>

如果你想要一个不错的 Validation.ErrorTemplate:

`<Style TargetType="x:Type TextBox">
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="Margin" Value="0,2,40,2" />
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="true">
                    <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                                ToolTip="Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent">
                        <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
                        </TextBlock>
                    </Border>
                    <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                        <Border BorderBrush="red" BorderThickness="1" />
                    </AdornedElementPlaceholder>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>`

【讨论】:

以上是关于ErrorTemplate 显示用户控件而不是其中的文本框!怎么修?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 WPF 中扩展控件以便为 ErrorTemplate 中的错误消息腾出空间?

浏览器控件 NavigateToString 显示 HTML 代码而不是渲染页面

有关如何使用软按钮而不是物理音量控件显示 Chromecast 音量滑块的示例代码

托管 WebBrowser 控件尝试下载 Flash 内容而不是播放它

Validation.ErrorTemplate 仅在至少一次没有错误时可见

GeoFire Android:GeoQuery 只显示最近的用户,而不是所有附近的用户