2013-07-01 28 views
0

所以,我为每个控件和ValidationErrorTemplate获得了一个巨大的样式模板字典。问题是,当控制器上方没有位置时,我们应该在控制下显示验证错误。基本上用于窗口顶部的控件。对于窗口底部的控件,验证应显示在控件的上方。WPF 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,具体取决于控件的顶部。

回答

0

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

[示例代码片段,在真正的源头更外包和复查,由于特定的代码问题]

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> 
0

有两个单独的模板(一个是另一个的对面),并且使用一个用于顶部的项目,一个用于底部的项目,只要任何对象包含您正在说的控件的任何对象。

+0

听起来不错,但我们不希望定义明确的风格与一键每一个控制。 Specialy不是,因为我们开发了一个框架,所以不能保证他们不会忘记添加正确的样式键。 –

+0

您是否想过使用DataTrigger来设置Grid.Row,取决于AdornedElementPlaceholder的值?我从来没有尝试过这个,但我认为它会按照你描述的方式工作。 – Killingsworth