解决方案 »

  1.   

    那个只是对颜色进行了自定义,我想做成下拉式的。那篇是Windows窗体应用程序,不是WPF。下拉菜单,有木有大神教我下。
      

  2.   

    参考:
    A Simple WPF Explorer Tree
    Reaction to: A Simple WPF Explorer Tree
      

  3.   

    第二篇是在WordPress上面的,因为被屏蔽掉了,所以可能你没打开。
    第二篇是针对第一篇中的图标是硬编码在Value Converter里面,并且是通过Heder的文本来判断这两个问题的改进。
    下面是我的翻译Reaction to: A Simple WPF Explorer TreeSacha Barber最近在CodeProject发表了一篇文章,标题为"A Simple WPF Explorer Tree"。这篇文章展示了怎么延迟加载目录结构的TreeView控件到电脑上。这是一篇非常好的WPF TreeView延迟加载的介绍文章,我强烈推荐阅读原文。
    在读完Sacha的这篇好文章后,我总感觉有点不对劲。在他的Demo中,树的根节点有个驱动器的图标,所有的其他节点有文件夹的图标。他对于使用哪种图标的实现逻辑是通过一个值转换器。一个TreeViewItem用来显示图标的图形元素的Source属性绑定到了TreeViewItem的Header上。这个绑定有一个转换器,转换器检查Header的文本里面是否有一个反斜杠(\),如果找到的话,那说明这是一个根节点 (比如它表示一个驱动器,而不是一个目录)。例如值转换器接收到的Header文本是"C:\",它就返回驱动器图标。
    值转换器包含了图标资源的名字,它通过那些硬编码的资源标识符去加载一个BitmapSource。这就是我觉得有问题的地方。我认为应该避免在值转换器和模板选择器中使用硬编码的资源标识符,因为这严重限制了这些累的重用性。
    至少有两种其他的方法可以用来实现图标选择功能而不需要在值选择器里面固定死资源的键值。第一种是允许你通过值选择器的属性来设置图标文件名 (资源标识符)。这样你就能指定XAML使用哪个图标,而值转换器只需要知道怎么解析它接收到的数据。
    我并不是很喜欢那个方法。事实上我想在这种情况使用值转换器并不是最好的方法。转换器的逻辑依赖于Header文本的某个字符虽然可以,但是我感觉和生硬。我认为TreeView结构和它的元素应该提供我们需要的所有信息,而不是元素数据里面的某个内容。
    我的解决方案为根节点提供一个属性,然后使用DataTriggers绑定这个属性并决定使用哪个图标。下面是代码。首先我们要有一个包含绑定属性的类,注意默认值是false:using System.Windows;namespace WpfExplorerTreeNoConverter
    { public static class TreeViewItemProps
    {
    public static bool GetIsRootLevel(DependencyObject obj)
    {
    return (bool)obj.GetValue(IsRootLevelProperty);
    } public static void SetIsRootLevel(
    DependencyObject obj, bool value)
    {
    obj.SetValue(IsRootLevelProperty, value);
    }

    public static readonly DependencyProperty IsRootLevelProperty =
    DependencyProperty.RegisterAttached(
    "IsRootLevel", 
    typeof(bool), 
    typeof(TreeViewItemProps), 
    new UIPropertyMetadata(false));
    }}(很抱歉这里的缩进有点奇怪,因为我的图片只能这么宽…)
    当我们初始化TreeViewItems的时候,它们代表电脑上的驱动器,我们把每个元素绑定的IsRootLevel属性设置为true:using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.IO;// NOTE: The original concept of this demo was created by Sacha Barber, in
    // this article: http://www.codeproject.com/useritems/WPF_Explorer_Tree.aspnamespace WpfExplorerTreeNoConverter
    {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary> public partial class Window1 : System.Windows.Window
    {
    private readonly object _dummyNode = null; public Window1()
    {
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(Window1_Loaded);
    } void Window1_Loaded(object sender, RoutedEventArgs e)
    {
    foreach (string drive in Directory.GetLogicalDrives())
    {
    TreeViewItem item = new TreeViewItem();
    item.Header = drive;
    item.Tag = drive;
    item.Items.Add(_dummyNode);
    item.Expanded += folder_Expanded; // Apply the attached property so that 
    // the triggers know that this is root item.
    TreeViewItemProps.SetIsRootLevel(item, true); foldersTree.Items.Add(item);
    }
    } void folder_Expanded(object sender, RoutedEventArgs e)
    {
    TreeViewItem item = (TreeViewItem)sender;
    if (item.Items.Count == 1 && item.Items[0] == _dummyNode)
    {
    item.Items.Clear();
    try
    {
    foreach (string dir in Directory.GetDirectories(item.Tag as string))
    {
    TreeViewItem subitem = new TreeViewItem();
    subitem.Header = new DirectoryInfo(dir).Name;
    subitem.Tag = dir;
    subitem.Items.Add(_dummyNode);
    subitem.Expanded += folder_Expanded;
    item.Items.Add(subitem);
    }
    }
    catch (Exception) { }
    }
    }
    }
    }最后,我们的模板指明每一个TreeViewItem的Header如何呈现。注意由于Header是通过ContentPresenter来展现的,我们需要绑定DataTriggers到一个可以找到相应的TreeViewItem相对资源:<Window x:Class="WpfExplorerTreeNoConverter.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfExplorerTreeNoConverter" 
        Title="WpfExplorerTreeNoConverter" Height="300" Width="300"
        >
      <Grid>    
        <TreeView x:Name="foldersTree">
          <TreeView.Resources>        
            <Style TargetType="{x:Type TreeViewItem}">
              <Setter Property="HeaderTemplate">
                <Setter.Value>              
                  <DataTemplate DataType="ContentPresenter">
                    <StackPanel Orientation="Horizontal">
                      <Image 
                        Name="img" 
                        Width="20" Height="20" 
                        Stretch="Fill" 
                        />
                      <TextBlock Text="{Binding}" Margin="5,0" />
                    </StackPanel>                <DataTemplate.Triggers>
                      <DataTrigger Binding="{Binding 
                        RelativeSource={RelativeSource 
                          Mode=FindAncestor, 
                          AncestorType={x:Type TreeViewItem}}, 
                        Path=(local:TreeViewItemProps.IsRootLevel)}" 
                        Value="True"
                        >
                        <Setter 
                          TargetName="img" 
                          Property="Source" 
                          Value="Images/diskdrive.png" 
                          />
                      </DataTrigger>                  <DataTrigger Binding="{Binding 
                        RelativeSource={RelativeSource 
                          Mode=FindAncestor, 
                          AncestorType={x:Type TreeViewItem}}, 
                        Path=(local:TreeViewItemProps.IsRootLevel)}" 
                        Value="False"
                        >
                        <Setter 
                          TargetName="img" 
                          Property="Source" 
                          Value="Images/folder.png" 
                          />
                      </DataTrigger>
                    </DataTemplate.Triggers>
                  </DataTemplate>              
                </Setter.Value>
              </Setter>
            </Style>        
          </TreeView.Resources>
        </TreeView>  
      </Grid>
    </Window>在这里下载演示项目: ExplorerTree (demo project) 请把文件后缀从.DOC改成.ZIP然后解压。
    译者按: 因为WordPress被屏蔽,所以想把资源上传到了CSDN,但是今天上传页面打不开,等恢复后再上传。但是关键代码上面已经贴上了。
      

  4.   

    WPF UI设计的帖子很不错。
      

  5.   

    你把StackPanel的Image节点和DataTemplate.Triggers节点都去掉看看