触发IDataErrorInfo时无法调整StackPanel的大小

时间:2016-10-24 07:48:18

标签: c# wpf xaml

当TextBox元素出错时自定义装饰器不会调整Textbox控件所在的StackPanel的大小: enter image description here

使用DockPanel.Bottom会使装饰器在下面的文本框中重叠。 代码我无耻地抬起http://hirenkhirsaria.blogspot.ie/2013/05/wpf-input-validation-using-mvvm.html

 <ControlTemplate.Resources>
        <Style x:Key="textblockErrorTooltip" TargetType="TextBlock">
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="Margin" Value="10 0 10 0" />
        </Style>
    </ControlTemplate.Resources>
    <DockPanel LastChildFill="true">
            <Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
                <TextBlock Style="{StaticResource textblockErrorTooltip}" Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
            </Border>
        <AdornedElementPlaceholder Name="customAdorner">
            <Border BorderBrush="#DC000C" BorderThickness="1.3" />
        </AdornedElementPlaceholder>
    </DockPanel>
</ControlTemplate>

当然,我可以使用Z Index,但我不喜欢它。

有没有办法让StackPanel在出错时调整大小?

我想在每个Textbox控件之后添加一个ContentTemplate:

<StackPanel>
  <TextBox/>
  <ContentTemplate/>
</StackPanel>

<StackPanel>
  <TextBox/>
  <ContentTemplate/>
</StackPanel>

ContentTemplate生成一个错误信息DataTemplate,我认为应该导致StackPanel调整大小。 但我无法弄清楚应该如何完成与(Validation.Errors)[0].ErrorContent}的绑定。 我的可怕尝试:

        <UserControl.Resources>
             <DataTemplate x:Key="errorinfo">
                <TextBlock>Hello World</TextBlock>
            </DataTemplate>
        </UserControl.Resources>
     <StackPanel Orientation="Horizontal" Grid.Row="4">
         <Label  Padding="0,0,20,0">Name:</Label>
            <StackPanel>
              <TextBox  Padding="0,0,10,0" Width="150" x:Name="name" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
            </StackPanel>
            <ContentControl >
               <ContentControl.Style>
                 <Style  TargetType="ContentControl">
                    <Setter Property="ContentTemplate" Value="{x:Null}"/>
                        <Style.Triggers>
                          <DataTrigger Binding="{Binding ElementName=name, Path=(Validation.HasError)}"  Value="True">
 <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <TextBlock Text="{Binding ElementName=name, Path=(Validation.Errors)[0].ErrorContent}"> </TextBlock>
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                         </DataTrigger>
                        </Style.Triggers>
                            </Style>
                        </ContentControl.Style>
            </ContentControl>
          </StackPanel>

我不能重复使用datatemplate!

我的问题类似于:WPF- Validation -The validation error message goes behind the other controls because of AdornerDecorator

我只想要一个不同的解决方案。

有什么想法吗?感谢

2 个答案:

答案 0 :(得分:0)

Adorner个图层与WPF中的主渲染图层分开。考虑Adorner的好方法只是作为图形叠加层,它包含Control元素标签环绕的形状(类似于Border的行为例如)。

对于每AdornerDecorator,您不需要单独的Control。这意味着理想的解决方案是在最高级别添加AdornerDecorator,例如Window,以便始终保证Adorner范围。

答案 1 :(得分:0)

我简直不敢相信!我自己想出来了:D

<UserControl.Resources>
        <Style x:Key="textblockErrorTooltip" TargetType="TextBlock">
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="Margin" Value="10 0 10 0" />
        </Style>

        <DataTemplate x:Key="errortemplate">
            <Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
                <TextBlock  Style="{StaticResource textblockErrorTooltip}" Text="{Binding Path=(Validation.Errors)[0].ErrorContent}"></TextBlock>
            </Border>
        </DataTemplate>

        <Style x:Key="ContentControlErrorTemplate" TargetType="ContentControl">
            <Setter Property="ContentTemplate" Value="{x:Null}"/>

            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=Children[1].(Validation.HasError)}"  Value="True">
                    <Setter Property="ContentTemplate" >
                        <Setter.Value>
                            <DataTemplate>
                                <Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
                                    <TextBlock  Style="{StaticResource textblockErrorTooltip}" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=Children[1].(Validation.Errors)[0].ErrorContent}"></TextBlock>
                                </Border>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
</UserControl.Resources>

  <StackPanel Orientation="Horizontal" Grid.Row="4">
    <Label  Padding="0,0,20,0">Name:</Label>
    <TextBox  Padding="0,0,10,0" Width="150" x:Name="name" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
    <ContentControl Style="{StaticResource ContentControlErrorTemplate}">
    </ContentControl>
  </StackPanel>

如果您有改进的想法,请告诉我。我不确定它有多高效但是有效。