代码之家  ›  专栏  ›  技术社区  ›  Joey

从非WPF代码访问WPF XAML资源

  •  7
  • Joey  · 技术社区  · 15 年前

    我目前正在构建一个由几个组件组成的应用程序,每个组件基本上都是一个WPF用户控件,周围有一些C代码,插件系统可以工作(使用MEF)。

    我所面临的问题是,每个组件都应该包含一个图标,为了便于识别,我将其定义为 System.Windows.Media.Brush 所以我可以用 DrawingBrush 从那里的设计导出。现在,我需要从非WPF C访问这段XAML,在这里我目前有一个可怕的解决方案,即实例化用户控件并请求它提供资源:

    private Brush CachedIcon = null;
    
    public override Brush Icon
    {
        get
        {
            if (CachedIcon == null)
            {
                CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon"));
            }
            return CachedIcon;
        }
    }
    

    我找不到读取该资源的方法(该资源是.xaml文件,并在 ResourceDictionary 在自定义控件中)从“Normal”C类。任何属于WPF的东西都有那么好 TryFindResource 方法,但如何做否则?我不想让图标未嵌入的XAML文件。

    4 回复  |  直到 13 年前
        1
  •  2
  •   TFD    15 年前

    在XAML代码中,确保icon资源的build选项设置为“resource”,然后引用该资源使其成为XAML静态资源。

    <UserControl.Resources>
        <BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" />
    </UserControl.Resources>
    

    然后在.NET 2.0代码中,您将在“xamlname.g.resource”流中找到该资源。

    将所有图标从XAML DLL加载到字典中的示例代码:

    using System.IO;
    using System.Reflection;
    using System.Collections;
    using System.Resources;
    
    ...
    
    var icons = new Dictionary<String, Bitmap>();
    var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll"));
    Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources");
    using (ResourceReader resourceReader = new ResourceReader(resourceStream)) {
        foreach (DictionaryEntry resourceEntry in resourceReader) {
            if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) {
                icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap);
            }
        }
    }
    
        2
  •  1
  •   Tim Cooper    13 年前

    我的建议是:

    • 在控件上提供有关可以在哪里找到图标的元数据。您可以使用自己的自定义属性来完成此操作(请参见下面的示例1)。此元数据将允许您在不创建控件实例的情况下加载图标。

    • 因为您使用的是MEF,所以可以在导出中使用元数据来实现与上面相同的效果。细节 here . 参见下面的示例2。

    • 将图标视为 ImageSource 而不是 Brush . 你可以用WPF Image 控件以显示 图像资源 或者你可以用 ImageBrush .

    • 使用tfd提供的技术读取元数据中指定名称的资源。不幸的是,WPF似乎没有提供类似 BamlReader 这将使从非WPF上下文加载WPF资源更加简单。

    例1:

    [Icon("MyIconResourceName")]
    public class BlahControl : Control
    {
        ...
    }
    

    例2:

    [Export(typeof(IApplicationComponent))]
    [ExportMetadata("IconResource", "MyIconResourceName")]
    public class BlahControl : Control
    {
        ...
    }
    
        3
  •  0
  •   boj    15 年前

    可以将程序集中的资源作为流读取。

    示例代码如下: http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html

        4
  •  0
  •   Lee Roth    15 年前

    在app.xaml或主资源字典xaml文件中,在app级别而不是控件中定义图标。然后可以使用相同的TryFindResource方法,但不创建控件的实例。