算法之递归(4) 应用

最近带着几个在做一个项目,UI层面用的是WPF。之前很少深入的接触WPF,不过接触后,发现WPF的却是很强大。

至少在界面设计上的用户体验较WinForm有了大幅提升。

项目中需要通用化几个样式,并将样式赋值给相应的控件。控件是根据配置文件动态生成的,配置文件是xml格式的层次化较多的结构。所以在动态生成的过程中采用了递归的方式来实现。

下面是一个模拟实例。

目标:

将程序集“PresentationFramework"的所有类型添加到TreeView里面,如果一个类型存在基类行,那么先加入基类型,以此类推。

实践:

1. 创建一个WPF应用程序,添加一个xml文件,放在工程的根目录下即可。(不用放在outputdir下面)。

2. 在此xml文件里,添加如下代码并保存。

<Style
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:System.Windows.Controls;assembly:PresentationFramework"
    TargetType="{x:Type TypeName=TreeViewItem}">
  <Setter Property="Foreground" Value="Yellow" />
  <Setter Property="FontFamily" Value="Comic Sans MS" />
  <Setter Property="FontSize" Value="18" />
  <Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
      <Setter Property="Background" Value="DarkBlue" />
    </Trigger>
  </Style.Triggers>
</Style>

3. 在MainWindow的cs文件中创建一个style解析器。代码如下。

        private void StyleParser()
        {
            using (FileStream fileStream = new FileStream(this.stylePath, FileMode.Open, FileAccess.Read))
            {
                this.myStyle = (Style)XamlReader.Load(fileStream);
            }
        }

4. 将”PresentationFramework"所有的类型以递归的形式添加到TreeView里面。

    (1) 定义递归算法。

        private void AppendItem(ItemsControl ctrl, Type type)
        {
            if (type.BaseType == null)
                return;

            TreeViewItem myTreeViewItem = new TreeViewItem(){ Header = type.FullName, Style = this.myStyle};
            ctrl.Items.Add(myTreeViewItem);
            AppendItem(myTreeViewItem, type.BaseType);
        }

    (2) 初始化TreeView,并调用AppendItem方法。

        private void Window_Loaded_1(object sender, RoutedEventArgs e)
        {
            ReLayout();

            myTreeView.Background = Brushes.SeaGreen;
            myTreeView.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            myTreeView.VerticalAlignment = System.Windows.VerticalAlignment.Top;

            myTreeView.Margin = new Thickness(5, 5, 0, 0);
            this.mainGrid.Children.Add(myTreeView);

            var asm = Assembly.GetAssembly(typeof(TreeViewItem));

            foreach (var type in asm.ExportedTypes)
            {
                var node = new TreeViewItem() { Header = type.FullName, Style = this.myStyle };
                myTreeView.Items.Add(node);
                AppendItem(node, type);
            }
        }

5. 定义一个ReLayout方法,用来调整TreeView控件在主窗体中的布局。并在“SizeChanged",”StateChanged“实践中调用该方法。

        private void ReLayout()
        {
            if (this.ActualHeight < 500)
                return;

            if (this.ActualWidth < 500)
                return;

            myTreeView.Height = this.ActualHeight - 50;
            myTreeView.Width = this.ActualWidth / 2;
        }

6. 运行,效果如下。

完整代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.IO;
using System.Reflection;

namespace WpfApplication8
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Style myStyle;
        private string stylePath = "..\\..\\CustomizedStyle.xml";
        private TreeView myTreeView = new TreeView();

        public MainWindow()
        {
            InitializeComponent();

            this.StyleParser();
        }

        private void StyleParser()
        {
            using (FileStream fileStream = new FileStream(this.stylePath, FileMode.Open, FileAccess.Read))
            {
                this.myStyle = (Style)XamlReader.Load(fileStream);
            }
        }

        private void AppendItem(ItemsControl ctrl, Type type)
        {
            if (type.BaseType == null)
                return;

            TreeViewItem myTreeViewItem = new TreeViewItem(){ Header = type.FullName, Style = this.myStyle};
            ctrl.Items.Add(myTreeViewItem);
            AppendItem(myTreeViewItem, type.BaseType);
        }

        private void Window_Loaded_1(object sender, RoutedEventArgs e)
        {
            ReLayout();

            myTreeView.Background = Brushes.SeaGreen;
            myTreeView.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
            myTreeView.VerticalAlignment = System.Windows.VerticalAlignment.Top;

            myTreeView.Margin = new Thickness(5, 5, 0, 0);
            this.mainGrid.Children.Add(myTreeView);

            var asm = Assembly.GetAssembly(typeof(TreeViewItem));

            foreach (var type in asm.ExportedTypes)
            {
                var node = new TreeViewItem() { Header = type.FullName, Style = this.myStyle };
                myTreeView.Items.Add(node);
                AppendItem(node, type);
            }
        }

        private void ReLayout()
        {
            if (this.ActualHeight < 500)
                return;

            if (this.ActualWidth < 500)
                return;

            myTreeView.Height = this.ActualHeight - 50;
            myTreeView.Width = this.ActualWidth / 2;
        }

        private void Window_StateChanged_1(object sender, EventArgs e)
        {
            ReLayout();
        }

        private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
        {
            ReLayout();
        }
    }
}
原文地址:https://www.cnblogs.com/lucasluo/p/2627524.html