【问题标题】:WPF - styling a lookless control: How to access dependecy properties of control from second level of ControlTemplates?WPF - 为无外观控件设置样式:如何从第二级 ControlTemplates 访问控件的依赖属性?
【发布时间】:2009-10-15 16:41:09
【问题描述】:

我正在扩展ItemsControl (class EnhancedItemsControl : ItemsControl),因为我想向它添加几个依赖属性——比如AlternativeContent,它将在集合中没有项目时显示(想想'输入搜索词并在项目控件中点击搜索标签以获取搜索结果)。

我将ItemsControl 子类化并添加了AlternativeContent 部门。 FrameworkElement 类型的属性。现在我想在 Themes/Generic.xaml 中提供默认样式(我已将 ThemeInfoAttribute 添加到 AsseblyInfo,并在静态 costructor 中提供了元数据,如 excellent tutorial 中所述)。

样式包含一个ControlTemplate,我需要在ItemsControl 模板中使用第二个ControlTemplate,我在其中添加一个ContentPresenter,它应该显示AlternativeContent

现在,我的问题是如何告诉ContentPresenter 它应该从顶级EnhancedItemsControl 获取其内容?如果我在风格的ControlTemplate 内,我会使用:

 Content="{Binding AlternativeContent, RelativeSource={RelativeSource TemplatedParent}}" 

但由于我在ItemsControlControlTemplate 内部样式的ControlTemplate 中,这显然不起作用,我需要参考的不是父模板,而是祖父模板,但是,TemplateBinding没有AncestorLevel 参数。

我也试过了:

 Content="{Binding AlternativeContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}"

但这也会导致空的ContentPresenter。我不能命名TemplatedParent(因为它在ControlTemplate 之外),所以我不能通过名称来引用它。我不能使用TemplatedParentRelativeBinding,因为这不会超过两个级别的控制模板。而RelativeSource FindAncestor 奇怪地不起作用。

知道如何解决这个问题吗?谢谢!

Generic.xaml(摘录):

 <Style TargetType="{x:Type WPFControls:EnhancedItemsControl}">
  <Setter Property="Template">
   <Setter.Value>
    <ControlTemplate TargetType="{x:Type WPFControls:EnhancedItemsControl}">
     <ItemsControl
      x:Name="RootItemsControl"
      ItemsSource="{Binding}"
      ItemTemplate="{TemplateBinding ItemTemplate}"
      Background="{TemplateBinding Background}"
      HorizontalContentAlignment="Stretch"
      >
      <ItemsControl.Template>
       <ControlTemplate>
        <ScrollViewer
         x:Name="ContentScrollViewer"
         CanContentScroll="False"
         >
         <StackPanel
          x:Name="InnerPanel"
          >

          <ItemsPresenter 
           Width="{Binding ActualWidth, ElementName=InnerPanel}"
           MaxWidth="{Binding ActualWidth, ElementName=InnerPanel}"
           HorizontalAlignment="Stretch"
           />

          <ContentPresenter 
          Content="{Binding AlternativeContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}" 
          >
           <ContentPresenter.Style>
            <Style>
             <Setter Property="ContentPresenter.Visibility" Value="Collapsed" />
             <Style.Triggers>
              <DataTrigger 
              Binding="{Binding Items.Count, ElementName=RootItemsControl}"
              Value="0">
               <Setter Property="ContentPresenter.Visibility" Value="Visible" />
              </DataTrigger>
             </Style.Triggers>
            </Style>
           </ContentPresenter.Style>
          </ContentPresenter>
         </StackPanel>
        </ScrollViewer>
       </ControlTemplate>
      </ItemsControl.Template>
     </ItemsControl>

    </ControlTemplate>
   </Setter.Value>
  </Setter>
 </Style>

控制代码:

 public class EnhancedItemsControl : ItemsControl
 {

  static EnhancedItemsControl()
  {
   DefaultStyleKeyProperty.OverrideMetadata(
    typeof(EnhancedItemsControl),
    new FrameworkPropertyMetadata(typeof(EnhancedItemsControl)));
  }


  public FrameworkElement AlternativeContent
  {
   get { return (FrameworkElement)GetValue(AlternativeContentProperty); }
   set { SetValue(AlternativeContentProperty, value); }
  }

  // Using a DependencyProperty as the backing store for AlternativeContent.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty AlternativeContentProperty =
   DependencyProperty.Register("AlternativeContent", typeof(FrameworkElement), typeof(EnhancedItemsControl), new UIPropertyMetadata(null));

 }

用法(List&lt;string&gt; 提供为DataContext):

 <WPFControls:EnhancedItemsControl Height="120" x:Name="EnhancedCollection"
  >
  <WPFControls:EnhancedItemsControl.AlternativeContent>
   <WPFControls:CenteredLabel>
    Alternative content
   </WPFControls:CenteredLabel>
  </WPFControls:EnhancedItemsControl.AlternativeContent>
  <WPFControls:EnhancedItemsControl.ItemTemplate>
   <DataTemplate>
    <TextBlock Text="{Binding}" />
   </DataTemplate>
  </WPFControls:EnhancedItemsControl.ItemTemplate>
 </WPFControls:EnhancedItemsControl>

【问题讨论】:

    标签: wpf dependency-properties controltemplate itemscontrol templatebinding


    【解决方案1】:

    哎呀,我的错,

    Content="{Binding AlternativeContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}" 
    

    确实有效(但我的标记比示例中的更复杂,并且由于其他错误没有显示内容...)

    【讨论】:

    • 这是一部非常酷的作品,我很高兴你分享了它。我想知道它是否可以在我的 WP7 手机上使用...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    相关资源
    最近更新 更多