簡體   English   中英

有沒有辦法在 WPF 控件庫中使用 StaticResource 並能夠在設計時查看?

[英]Is there any way to use StaticResource in a WPF control library and be able to view at design-time?

我有一個 WPF 控件庫,它被添加到一個 windows forms 應用程序中。 我們希望允許控件本地化,但是我不確定如何在不復制代碼的情況下完全實現這一點。 這就是我現在正在做的

基本上,在 windows forms 應用程序中,在主應用程序啟動之前,我正在實例化一個位於 forms 應用程序中的 App.xaml(包含我的資源鏈接也位於 forms 應用程序中)。 這非常適合運行時。

但是,我的用戶控件都有Content="{StaticResource SomeVariableName}" ,最終都是空白的。 我可以通過在我的控制庫中擁有一個 app.xaml 和適當的資源字典來解決這個問題,這些字典與我的 windows forms 應用程序中的相匹配。 但是,這是重復的代碼。

我已經嘗試過但無濟於事的事情:

  • 從我的 forms 應用程序中實例化位於用戶控件庫中的 App.xaml。 這不起作用,因為我的資源的 URI 正在尋找嵌入式資源,而不是我的本地資源字典(然后我可以簡單地將資源文件從控件復制到我的 forms 應用程序中的適當位置)。 我可以在這里利用DeferrableContent嗎? 不過,據我所知,關於此屬性及其使用方式的在線資料並不多。
  • 我想對 App 和字典使用后期構建,但是,據我所知,App 實例化是一個 static 對已編譯 App.xaml 的引用。 因此,App.xaml 必須至少存在於表單中
    • 我確實嘗試過復制 App.xaml,並在構建后移動 resourcedictionary.xaml。 我認為重復的 app.xaml 是可以的,因為它是驅動力,你可能不想依賴控件中的一個(它回過頭來讓你想知道你是否應該在控件中使用 App.xaml全部?除非你想允許使用嵌入式資源的默認值......)即使它被放置在 URI 應該指向的位置,它也找不到資源。 反編譯后的代碼指向Uri resourceLocater = new Uri("/WindowsFormsApplication3;component/app.xaml", UriKind.Relative);

那么,有什么方法可以讓它工作並在設計時查看組件默認值並避免重復? 或者,在這種情況下復制可以嗎? 如果我的第二個項目符號的子項看起來沒問題(復制的 App.xaml 和構建復制的資源字典),我如何讓它不查找組件級項目,而是查找文件級項目?

我剛剛關注的最后一個問題(如有必要,我可以單獨發布)。 我的 App.xaml 正在構建到代碼中,因此無論如何我都不允許動態創建新的 ResourceDictionaries。 有什么辦法嗎?

最后的選擇……可能是最好的選擇? -我打算無論如何都使用 Andre van Heerwaarde 的代碼,所以我是否應該檢查文件是否存在並將其添加為動態合並資源? 基本上,在我的用戶控件中有一個 App.xaml 鏈接到默認的嵌入式 ResourceDictionary。 然后讓代碼動態查找合適的本地化資源,這些資源可以是相對文件路徑? 我在這里看到的唯一缺點是無法即時更改默認值……我什至可以在指定位置(使用某種約定)查看它,並且比內置的更受歡迎?

哦,我不想要嵌入式資源的原因是最終用戶可以在部署構建后添加/修改新的本地化資源。

如果可以幫助您更好地形象化,我可以添加代碼,請告訴我。

更新

我現在遇到了樣式方面的進一步問題,而不僅僅是本地化。

這是其中一個控件上的內部按鈕之一的示例:

<Button Style="{StaticResource GrayButton}"

我嘗試/想到的更多事情:

  • 我無法使用 ResourceDictionary 設置創建 app.xaml(永遠不會使用),因為庫項目中不允許使用 ApplicationDefinitions。 我可以將它嵌入到控件的資源中,但是那樣的話它總是優先於任何應用程序級別的資源並且我失去了可定制性。

這是一個實際上聽起來像我正在尋找的連接案例,但是它沒有為此提供任何真正的解決方案

我能想到的可能有效(並且尚未嘗試)的解決方案(超出頂部......不起作用)對於我認為應該很簡單的事情來說似乎也需要大量工作。 但是,我也許能夠在我可以綁定到的控件中創建一些依賴屬性,然后允許將使用該控件的項目覆蓋這些屬性。 正如我所說,對於一個非常簡單的請求來說,這似乎需要大量工作:)。 這甚至可以工作嗎? 更重要的是,是否有我缺少的更好、更簡單的解決方案?

我曾經遇到過這個問題,我通過刪除整個“資源是規范詞典中的鍵索引的對象”來解決它。

我的意思是,在一個項目中定義資源並通過它的“鍵”在另一個項目中引用它這個簡單的事實應該會讓任何理智的人起雞皮疙瘩。 我想要強有力的參考。

我對這個問題的解決方案是創建一個自定義工具,將我的資源 xaml 文件轉換為 static 類,每個資源都有一個屬性:

所以我的資源.xaml:

<ResourceDictionary>
  <SolidColorBrush x:Key="LightBrush" ... />
  <SolidColorBrush x:Key="DarkBrush" ... />
</ResourceDictionary>

變成 MyResources.xaml.cs

public static class MyResources {

  static MyResources() {
    // load the xaml file and assign values to static properties
  }

  public static SolidColorBrush LightBrush { get; set; }
  public static SolidColorBrush DarkBrush { get; set; }

}

要引用資源,您可以使用x:Static而不是StaticResource

<Border 
   Fill="{x:Static MyResources.LightBrush}"
   BorderBrush="{x:Static MyResources.DarkBrush}"
   ... />

現在您獲得了資源的強引用、自動完成和編譯時檢查。

我在處理樣式主題和可用資源 static 時也遇到了問題。 因此,我創建了一個獨立的庫,它基本上只有要使用的主題,所有主題都嵌套在一起,就像您之前鏈接問題的 MERGED 資源一樣。

然后,在 Windows 表單 (.xaml) 中,我只是引用了那個庫,比如

<Window x:Class="MyAppNamespace.MyView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ... />

  <Window.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <!-- Common base theme -->
        <ResourceDictionary   Source="pack://application:,,,/MyLibrary;component/Themes/MyMainThemeWrapper.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Window.Resources>

  <Rest of XAML for the WPF window>

</Window>

“組件”似乎是指給定“MyLibrary”項目的根目錄。 在實際項目中,我創建了一個名為“Themes”的子文件夾,因此源包括... ;component/Themes/...

“MyMainThemeWrapper.xaml”非常類似於嵌套的合並資源字典,它可以完美地查看其他庫中的所有內容。

這是我對您的問題的部分解決方案。 我沒有嘗試處理松散的資源,但我在 WinForms 和 WPF 之間共享資源方面取得了一些成功。

  • 創建一個 class 庫以將您的資源包含在 .ResX 文件中(例如 Resources.resx、Resources.fr.resx 等)
  • 在 WPF 用戶控件庫中創建您的 WPF 控件
  • 創建您的 WinForms 主機
  • 使用Infralution.Localization.Wpf標記擴展和文化管理器從 WPF 引用資源庫中的資源,例如

    <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
  • 將你的 WPF 用戶控件的內容放入一個或多個資源字典中作為控件模板,e,g

     <ControlTemplate x:Key="TestTemplate"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/> </Grid> </ControlTemplate>
  • 在用戶控件中使用資源模板

    <UserControl x:Class="WpfControls.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" > <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ResourceDictionary.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <ContentControl Template="{StaticResource TestTemplate}" /> </UserControl>
  • 添加幾行代碼使一切正常

    public partial class UserControl1: UserControl { // we require a reference to the resource library to ensure it's loaded into memory private Class1 _class1 = new Class1(); public UserControl1() { // Use the CultureManager to switch to the current culture CultureManager.UICulture = Thread.CurrentThread.CurrentCulture; InitializeComponent(); } }

這是一個名為 WindowsFormsHost.7z 的簡單演示應用程序

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM