缩进wpf树视图中的顶级分层项

时间:2016-09-02 09:54:35

标签: c# wpf treeview

我试图在WPF TreeView中的顶级层次结构项之间提供分隔(边距)。问题是,我无法弄清楚如何编写Style,只能应用于顶级项目而不是每个项目。

TreeView的代码如下所示:

<TreeView ItemContainerStyle="{StaticResource treeViewItemStyle}"
          ItemsSource="{Binding Container.RootRules}"
          KeyUp="treeView_KeyUp"
          SelectedItemChanged="TreeView_SelectedItemChanged">
  <TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type me:HybridForecastRulesViewModel}"
                              ItemsSource="{Binding Children}">
      <Border Name="bd"
        ...
      </Border>
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate DataType="{x:Type me:RootRulesViewModel}"
                              ItemsSource="{Binding Rules}">
      <Grid>
        ...
      </Grid>
    </HierarchicalDataTemplate>
  </TreeView.Resources>
</TreeView>

我有一个像这样的treeViewItems样式:

<Style x:Key="treeViewItemStyle"
       BasedOn="{StaticResource {x:Type TreeViewItem}}"
       TargetType="{x:Type TreeViewItem}">

  <Setter Property="Margin" Value="0,10,0,0" />

  <Style.Triggers>
    <DataTrigger Binding="{Binding IsVisible}" Value="False">
      <Setter Property="Visibility" Value="Collapsed" />
    </DataTrigger>
  </Style.Triggers>

</Style>

但是,当我希望它仅适用于RootRulesViewModel类型的项目时,此样式适用于这两种类型的项目(HybridForecastRulesViewModelRootRulesViewModel)。如何才能做到这一点?

除了第一个RootRulesViewModel之外,所有Margin个项目的最高[Exception:Cant get object from dataabase for blabla.... at NHibernate.Proxy.CastleProxyFactory.GetProxy(Object id, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.CreateProxy(Object id, ISessionImplementor session) at NHibernate.Impl.SessionImpl.DoLoadByClass(Type clazz, Object id, Boolean checkDeleted, Boolean allowProxyCreation) at NHibernate.Impl.SessionImpl.InternalLoad(Type clazz, Object id) at NHibernate.Type.ManyToOneType.ResolveIdentifier(Object id, ISessionImplementor session) at NHibernate.Type.EntityType.ResolveIdentifier(Object id, ISessionImplementor session, Object owner) at NHibernate.Impl.SessionImpl.InitializeEntity(Object obj) at NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList hydratedObjects, Object resultSetId, ISessionImplementor session) at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes) at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session) at NHibernate.Impl.SessionImpl.Find(CriteriaImpl criteria, IList results) at NHibernate.Impl.SessionImpl.Find(CriteriaImpl criteria) at NHibernate.Impl.CriteriaImpl.List() at Main.GetUser() in c:\inetpub\app\WebSites\app\App_Code\Main.cs:line 40] Main.GetUser() in c:\inetpub\app\WebSites\app\App_Code\Main.cs:53 GetData..ctor() in c:\inetpub\app\WebSites\app\App_Code\GetsData.cs:20 Start..ctor() in c:\inetpub\app\WebSites\app\Start.aspx.cs:28 ASP.begin_aspx..ctor() in c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\940436d6\b67d273a\App_Web_zf-pdvkp.10.cs:0 __ASP.FastObjectFactory_app_web_zf_pdvkp.Create_ASP_begin_aspx() in c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\940436d6\b67d273a\App_Web_zf-pdvkp.18.cs:0 System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +138 System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +50 System.Web.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +425 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +263 都是锦上添花。

2 个答案:

答案 0 :(得分:1)

TreeViewItem没有Level属性可供使用。

所以你有两个选择:

1)this。看看TreeLevelConverter,这很有趣。它们绑定控件本身并使用转换器来检索Level。在您的情况下,您可以在检索Level后扩展转换器,将其转换为Thickness实例以用作Margin

2)您可以在Level上创建ViewModels属性(可能在其基类中,以避免代码重复)。然后,每次将子项添加到ViewModel节点时,都会在该子项上设置Level。在xaml中,您将Margin属性绑定到Level上的ViewModel,使用转换器返回不同的Thickness,具体取决于Level是否为1或不

修改

这是您为所有Style

设置公共TreeViewItem的方法
<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
      <Setter 1 .../>
      <Setter 2 .../>
      <Setter Property="Margin"
              Value="{Binding Level, Converter={StaticResource LevelToMarginConverter}}"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.Resources>
    <!-- here your hierarchical DataTemplate... -->
    <HierarchicalDataTemplate ... />
  </TreeView.Resources>
</TreeView>

答案 1 :(得分:0)

我实际上最终得到了一个解决方案。我不确定它有多好,所以可以提出改进建议。

我已经从this answer编写了一个对象转换器,以获取Header的{​​{1}}中的对象类型。 代码如下所示:

TreeViewItem

<Style.Triggers> <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Header, Converter={StaticResource ObjectTypeConverter}}" Value="RootRulesViewModel"> <Setter Property="Margin" Value="0,0,0,10" /> </DataTrigger> <DataTrigger Binding="{Binding IsVisible}" Value="False"> <Setter Property="Visibility" Value="Collapsed" /> </DataTrigger> </Style.Triggers> </Style> 是我的自定义转换器,它将对象类型转换为字符串值。