[英]Resources in modularized WPF (with Caliburn.Micro and MEF)
我整天都在尋找這個問題的答案,而沒有提出任何直接適用於我的情況的解決方案,或者沒有任何可行的解決方案(在我發現的情況下適用)。
我設置了一個Caliburn.Micro框架以使用MEF,並且可以很好地加載我的模塊化元素。 缺少的一件事是讓WPF識別我在一個模塊中使用的資源。
如何在我的應用程序引導程序中加載模塊
[ImportMany]
private IEnumerable<IMyModule> _myModules;
protected override void Configure()
{
// Because Configure() is also called from SelectAssemblies(), we cannot instantiate MEF again because it will create conflicts.
if (_configured)
{
return;
}
AggregateCatalog aggregateCatalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(ConfigurationManager.AppSettings["MyModuleFolderLocation"]));
aggregateCatalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly));
_container = new CompositionContainer(aggregateCatalog);
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(_container);
_container.Compose(batch);
_container.SatisfyImportsOnce(this);
_configured = true;
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
// SelectAssemblies() is called before Configure(), so manually force Configure() to run first so that MEF is instantiated properly
Configure();
if (!_configured)
{
throw new Exception("Unable to configure assemblies");
}
List<Assembly> assemblies = new List<Assembly>();
assemblies.Add(Assembly.GetExecutingAssembly());
// Need to add all module assemblies so that Caliburn will be able to find the View for a ViewModel
foreach(IMyModule myModule in _myModules)
{
Assembly assembly = myModule.GetType().Assembly;
assemblies.Add(assembly);
}
return assemblies.Distinct();
}
這樣可以使模塊正確顯示。
但是,當模塊使用圖像時,就永遠不會顯示該圖像,因為這種加載顯然沒有考慮資源。 我在模塊項目中創建一個Resources.resx文件,並向其中添加一個圖像。 然后,Visual Studio中提供的圖像文件將具有一個“顯示資源”和“請勿復制(到輸出目錄)”的“生成操作”。 這應該意味着圖像已嵌入到生成的DLL文件中。
該圖像放置在模塊項目中的一個名為“ Resources”的文件夾中,XAML像這樣使用它:
<Image Source="/Resources/myImage.png" />
該圖像顯示在Visual Studio的預覽中,但在應用程序運行時不顯示。
我嘗試過的沒有用
<Image Source="pack://application:,,,/Resources/myImage.png" />
var reader = new Baml2006Reader(stream);
) 問題仍然存在
如何獲取WPF / Caliburn.Micro來識別MEF加載的DLL中的資源?
使用帶有Build Action: Resource
圖像的Source
屬性使用此語法
<Image Source="/AssemblyName;component/Resources/MyImage.png" />
其中AssemblyName
是程序集的名稱(在項目屬性中定義),/ /Resource/MyImage.png
是圖像的路徑(在項目中定義)。 component
必須始終存在。
在@StepUp的大量幫助下,我最初決定使用從該問題中學到的知識來提出一個新問題,並將所有內容重新措辭更具體地針對我的問題。
在寫這個新問題時,我最終搜索了可能有助於改寫的短語和命令,然后偶然發現了以下頁面: http : //www.geekchamp.com/tips/wp7-working-with-images-content-vs -resource建造行動
顯然,WPF Image控件具有大量的方法來定義Source屬性。 我已經嘗試了很多不同的Source輸入,並認為我已經嘗試了所有這些輸入,但是上面鏈接的頁面證明我錯了。
據我所能測試,上述語法似乎適用於標有Build Action: Resource
圖像。 因此,我不再需要圖像的RESX文件,並且在引導MEF時不需要任何特殊處理。
首先,您應該使用Style
閱讀程序集。 然后,有必要使用Baml2006Reader
從外部庫讀取BAML文件。 讓我舉一個例子:
private GetResourceDictionary()
{
string address = @"WpfCustomControlLibrary1.dll";
Assembly skinAssembly = Assembly.LoadFrom(address);
string[] resourceDictionaries = skinAssembly.GetManifestResourceNames();
Stream bamlStream = null;
string name = "themes/AllStylesDictionary.baml";//themes/AllStylesDictionary.baml
foreach (string resourceName in resourceDictionaries)
{
ManifestResourceInfo info = skinAssembly.GetManifestResourceInfo(resourceName);
if (info.ResourceLocation != ResourceLocation.ContainedInAnotherAssembly)
{
Stream resourceStream = skinAssembly.GetManifestResourceStream(resourceName);
using (ResourceReader reader = new ResourceReader(resourceStream))
{
foreach (DictionaryEntry entry in reader)
{
if (entry.Key.ToString().Equals(name.ToLower()))
{
bamlStream = entry.Value as Stream;
}
}
}
}
}
ResourceDictionary rd = LoadBaml<ResourceDictionary>(bamlStream);
Application.Current.Resources.MergedDictionaries.Add(rd);
Style style = Application.Current.Resources.MergedDictionaries[0]["myStyle"] as Style;
button.Style = style;
}
和:
public static T LoadBaml<T>(Stream stream)
{
var reader = new Baml2006Reader(stream);
var writer = new XamlObjectWriter(reader.SchemaContext);
while (reader.Read())
writer.WriteNode(reader);
return (T)writer.Result;
}
更新:
如果要從另一個庫加載映像,則應使用以下代碼:
yourImage.Source = new Bitmap(System.Reflection.Assembly.GetEntryAssembly().
GetManifestResourceStream("MyProject.Resources.myimage.png"));
UPDATE1:
要從外部dll
加載映像。
foreach (DictionaryEntry entry in reader)
{
if (entry.Key.ToString().Equals(name.ToLower()))
{
bamlStream = entry.Value as Stream;
BitmapImage bmp = LoadImage(bamlStream);
img.Source = bmp;
}
}
public static BitmapImage LoadImage(Stream stream)
{
BitmapImage bmi;
using (MemoryStream ms1 = new MemoryStream())
{
stream.CopyTo(ms1);
bmi = new BitmapImage();
bmi.BeginInit();
bmi.StreamSource = new MemoryStream(ms1.ToArray());
bmi.EndInit();
}
return bmi;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.