【问题标题】:WPF ValidationErrorTemplate style dynamic positionWPF ValidationErrorTemplate 样式动态定位
【发布时间】:2013-07-01 14:40:34
【问题描述】:

所以,我为每个控件和 ValidationErrorTemplate 获得了一个巨大的样式模板字典。问题是,当控件上方没有位置时,我们应该在控件下方显示验证错误。基本上用于窗口顶部的控件。对于窗口底部的控件,验证应显示在控件上方。

因为它是一个定义了每种样式的资源字典,所以没有代码隐藏,而且没有数据绑定是可能的。

一个想法是确定AdornedElementPlaceholder 的位置并分别隐藏/显示模板。但我在 XAML 中没有找到任何解决方案。

    <ControlTemplate x:Key="ValidationErrorTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="1">
                <Border>
                    <AdornedElementPlaceholder />
                </Border>                
            </Grid>
            <AdornerDecorator Grid.Row="????">
                <Border >
                    <!-- some style comes here ...  -->
                </Border>
            </AdornerDecorator>
        </Grid>
    </ControlTemplate>

Grid.Row="????" 应为 0 或 1,具体取决于控件的顶部。

【问题讨论】:

    标签: c# wpf validation controltemplate resourcedictionary


    【解决方案1】:

    有两个单独的模板(一个与另一个相反),一个用于顶部的项目,一个用于底部的项目,只要包含您所说的控件的任何对象都认为合适。

    【讨论】:

    • 听起来不错,但我们不想为每个带有键的控件显式定义样式。特别不,因为我们开发了一个框架,所以不能保证他们不会忘记添加正确的样式键。
    • 您是否考虑过根据 AdornedElementPlaceholder 的值使用 DataTrigger 来设置 Grid.Row?我以前从未专门尝试过这个,但我认为它会按照你描述的方式工作。
    【解决方案2】:

    所以我终于找到了解决方案:附加属性。我创建了一个附加属性,并在 AdornerDecorator.Loaded 事件上订阅的属性更改回调方法上。在该方法中,您可以检查实际位置并根据需要更改属性。

    [示例代码-sn-p,在真实源代码中,由于代码特定问题,更多外包和重新检查]

    private static void DecoratorLoaded(object obj, RoutedEventArgs e)
    {
         var decorator = obj as Decorator;
         if (decorator != null && decorator.IsVisible)
         {
            // get the position
            Point renderedLocation = decorator.TranslatePoint(new Point(0, 0), Application.Current.MainWindow);
            if (renderedLocation != new Point(0, 0))
            {
               // check width
               var maxAllowedWidth = Application.Current.MainWindow.ActualWidth - renderedLocation.X - 40;               
               decorator.SetValue(FrameworkElement.MaxWidthProperty, maxAllowedWidth);
    
               // check place above the control
               var isEnoughPlaceAbove = renderedLocation.Y > decorator.ActualHeight + 10;
               decorator.SetValue(Grid.RowProperty, isEnoughPlaceAbove ? 0 : 2);
    
               // invalidate to re-render
               decorator.InvalidateVisual();               
            }
         }
    }
    

    您需要使用Loaded 事件来确保renderLocation 将为您提供实际位置,而不是其他东西(例如零或一些相对位置)。

    最后你需要将附加属性附加到 XAML 中的装饰器:

    <AdornerDecorator Behaviors:AdornerPositionCalculator.AllowDynamicPosition="True">
      <!-- custom style here -->
    </AdornerDecorator>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 2011-05-07
      相关资源
      最近更新 更多