【问题标题】:Unable to resize StackPanel when IDataErrorInfo is triggered触发 IDataErrorInfo 时无法调整 StackPanel 的大小
【发布时间】:2023-04-01 13:33:01
【问题描述】:

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

使用 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 索引,但我不喜欢它。

有没有办法让 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>

虽然我不能重用数据模板!

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

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

有什么想法吗?谢谢

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    Adorner 层与 WPF 中的主要渲染层分开。考虑Adorner 的一个好方法是简单地作为一个图形覆盖层,它包含Control 的形状,它的元素标签环绕(类似于Border 的行为)。

    您不需要为每个 Control 提供单独的 AdornerDecorator。这意味着理想的解决方案是将AdornerDecorator 添加到可能的最高级别,例如Window,以便始终保证Adorner 范围。

    【讨论】:

    • 嗨,我不希望每个控件都有一个 AdornerDecorator。只是为了使用属性 Validation.HasError 上的数据触发器生成一个文本块控件,因为正如您所说的 Adorner 作为不同的渲染层
    【解决方案2】:

    我不敢相信!我自己想出来的: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>
    

    如果您有改进的想法,请告诉我。我不确定它的效率如何,但它确实有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多