65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 的样式浏览器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (9投票s)

2011 年 4 月 25 日

CPOL

5分钟阅读

viewsIcon

38332

downloadIcon

2665

用于预览 WPF 中 XAML 样式的应用程序。

引言

在本文中,我将向您展示一个可以帮助您浏览 XAML 样式的简单应用程序。您可以从上面的链接下载源代码。

背景

我相信每个 WPF 开发人员都遇到过这样的问题:大量的样式……大量的图像、画笔、不同的文本框和文本块。有时很难找到所需的资源键。这个问题在有很多自定义控件的大型 WPF 项目中经常遇到。当有多个开发人员时——这会更加困难!但对于某些情况,有一个相当简单的解决方案。本文介绍的应用程序可以帮助您简化此过程。使用 StyleBrowser,您可以选择一些 XAML 并“查看”其内部。该应用程序将向您显示指定 XAML 文件中存储的所有样式、图像和画笔。

此外,当您想使用之前创建但不记得 XAML 文件中确切内容的样式时,也可以使用此应用程序。只需打开 XAML,找到所需的样式,然后使用它!

使用应用程序

打开应用程序后,您将看到以下屏幕

按“选择 XAML”,您的桌面上将出现一个打开对话框。选择包含样式的 XAML 文件,然后按确定。如果 XAML 已解析,您将看到类似以下内容

在应用程序的中间,有一个 TabControl,包含多个选项卡。每个选项卡都是 XAML 中某些样式的一个组。在截图中,打开了“Buttons”选项卡,您可以看到 XAML 中的按钮。“Sample content”会自动添加到具有 Content 属性的每个控件中。使用反射进行检测。右侧是样式键及其类名。所有样式都按字母顺序排序。

此外,还有两个有用的功能可以帮助您。您可以选择背景,因为有些样式是白色的,有些是黑色的……有些是黑白色的 :)。目前,只有三种预定义颜色:黑色、白色和灰色。我认为将来会有类似颜色选择器之类的东西。

第二个功能是搜索。只需在搜索文本框中键入任何单词,您将只看到与搜索文本匹配的样式。颜色和搜索显示在下图

最后一个有趣的有用功能是您可以查看 XAML。只需点击您想查看的样式右侧的“XAML”按钮。但是这个功能有一个缺点:它会显示带有完全限定类名和 XML 命名空间的 XAML。但是简单的 XAML 看起来不错,并且可能很有用。

代码截图

让我们简要浏览一下代码,看看它是如何工作的。一开始,使用 OpenDialog 选择文件。

要解析 XAML,我只需使用以下代码

XamlReader reader = new XamlReader();
FileStream stream = new FileStream(dlg.FileName, FileMode.Open);
Uri uri = new Uri((new FileInfo(dlg.FileName)).Directory.FullName + "\\");
object xaml = reader.LoadAsync(stream, new ParserContext() { BaseUri = uri });

我们必须在此处指定 BaseUri,以便解析器能够处理相对路径到图像或其他文件(如果它们存在于 XAML 中)。

此代码有一个缺点。如果标签无法解析,XAML 将根本不会被读取。所以我们有这样的限制:XAML 只能包含源编译的 .NET 版本中默认定义的命名空间。我的解决方案使用 .NET 4.0。

另外,您应该小心图像路径。

下一步是用加载的样式填充当前窗口的资源。我们需要这样做,因为有些样式会使用该 XAML 中的其他样式。如果我们不将 XAML 复制到资源中,则引用的 XAML 将不会被加载。

this.Resources.Clear();
if (xaml is ResourceDictionary)
{
    foreach (DictionaryEntry item in (xaml as ResourceDictionary))
    {
        this.Resources.Add(item.Key, item.Value);
        entries.Add(item);
    }
}

目前,此代码还有另一个问题:有时主窗口中在其资源中有其样式的控件会改变其外观,即使该控件不在预览区域中。我将在将来修复这个问题。

所以我们有样式、画笔和图像的集合。我们可以用它做任何事情。排序、分组等。在我的应用程序中,样式按字母顺序排序。

下一个任务是遍历集合中的每个项目,并在相关的选项卡控件中创建预览。

foreach (var item in list.OrderBy(e => e.Key.ToString()))
{
    StyleItem styleItem = null;
    DictionaryEntry entry = (DictionaryEntry)item;
    if (entry.Value is Style)
    {
        Style style = entry.Value as Style;
        Type type = style.TargetType;
        object obj = Activator.CreateInstance(type);
        
        if (obj is AnimationTimeline) continue;

        styleItem = new StyleItem(obj as FrameworkElement, 
                                  style, type, entry.Key.ToString());

        if (type == typeof(Button) || type == typeof(ToggleButton))
        {
            buttonsPanel.Children.Add(styleItem);
        }

StyleItem 是一个表示样式预览的自定义控件。每个 DictionaryEntry 都有一个 KeyValue(就像字典一样 :))。Key 是 XAML 中的 x:Key 属性。Value 是 XML 元素的内容。

我们必须检查值的类型,因为例如,如果当前项目是图像,您就不能应用 Style 属性。此外,我们需要跳过任何动画,因为无法为动画创建通用预览。如果项目是画笔或图像,我只需将预览的背景设置为图像或画笔。

如果项目是 Style,有三行重要代码,它们提取样式、对象类型,并创建提取类型的实例。

Style style = entry.Value as Style;
Type type = style.TargetType;
object obj = Activator.CreateInstance(type);

然后 StyleItem 使用此信息来创建 TabControl 中相关的预览项。

另一个有趣的事情是如何创建预览 XAML 文本。

string xaml;
try
{
    xaml = XamlWriter.Save(entry.Value).Replace(">", ">\n").NormalizeXaml();
}
catch { xaml = "XAML cannot be parsed"; }

为什么在这里使用 Replace 方法?因为 Save() 返回一个不带换行符的字符串。所以我决定在每个“>”之后插入一个换行符。

此外,还有一个 String 的扩展方法:NormalizeXaml()

此方法根据 XML 中的深度在每行开头插入空格。我不确定是否应该在这篇文章中展示此方法的实现。

限制和未来

目前,此应用程序存在一些问题。但是,如果您觉得它有用,请告诉我。如果开发人员喜欢这个应用程序的功能,我将继续努力并添加新的有用功能并修复当前问题。

将来,我将

  • 跳过有错误的样式。
  • 添加包含资源的 DLL。
  • 添加不同 XAML 的功能。例如,如果一个 XAML 引用了另一个 XAML 中定义的样式。
  • 添加颜色选择器来选择自定义背景颜色。
  • 清理 XAML 源查看器中的命名空间和完全限定路径。
  • 创建一个更智能的对象创建器。例如:为菜单、选项卡控件和其他具有复杂内容的控件使用预定义的 Content 模板。
  • 使预览区域可调整大小。例如,一个小的文本需要一个小的矩形,而滑块或图像有时需要一个巨大的区域。
  • 也许您会告诉我一些可以包含的有趣功能。
© . All rights reserved.