【问题标题】:Resource based on objects in WPF基于 WPF 中对象的资源
【发布时间】:2013-09-15 14:20:24
【问题描述】:

在一个单独的项目中,我有一个反序列化的 xml 文件,其中包含我想在我的 WPF 应用程序中使用的字符串,这些字符串也在同一解决方案的不同项目中使用,所以我不能只移动字符串转到持有 wpf 应用程序的项目。

程序的结构如下:

项目 A 参考 B 和 C

  • 带有事件处理程序的 WPF 应用程序

项目 B 参考 C

  • F# 中的 GUI 逻辑

项目 C

  • XML 资源文件和反序列化器(用 F# 编写)

有没有办法让我根据反序列化的 xml 文件中的对象制作资源或资源字典?或者我可以直接引用存储在xml文件中的字符串吗?

【问题讨论】:

  • 反序列化的对象只是一个带有一些字符串属性的类吗?您可以简单地将其设置为单例,然后直接访问属性。为什么需要资源字典?
  • 因为它必须被 2 个项目访问,所以制作一个动态反序列化的 xml 文件非常容易使用......也就是说,如果 wpf 允许一种简单的方法来包含外部资源跨度>
  • 我有点困惑 - 为什么你使用 XML 作为字符串而不是项目的资源选项?
  • @ChandramouleswaranRavichandra 可以跨多个项目工作吗?还是我必须在每个项目上添加相同的资源?
  • 是的,应该可以。请参阅 Borislav Ivanov 的解决方案。

标签: c# xml wpf xaml resource-files


【解决方案1】:

我建议您使用内置的 .resx 文件,该文件默认包含在新创建的 WPF 应用程序中。 (您也可以稍后使用Project -> Add New Item... -> Resource File 添加它。)只要确保将访问修饰符设置为“Public”,您就可以在引用当前项目的其他项目中使用这些字符串:
@987654323 @
您将能够通过自动生成的强类型包装类访问字符串(以及其他资源!):

MessageBox.Show(WpfApplication1.Properties.Resources.String1);

您还可以使用 XAML 为存储在此文件中的字符串设置属性,使用 x:Static markup extension,如(例如)this answer 中所述:

xmlns:resx="clr-namespace:WpfApplication1.Properties;assembly=WpfApplication1" 
Title="{x:Static resx:Resources.String1}"

此外,您还将获得漂亮的 Visual Studio 内置 UI,用于编辑文件(在图片中也可见)。

【讨论】:

  • 您的解决方案存在一个小问题; f#项目看不到wpf项目,所以在f#项目中不引用wpf项目就无法访问;但是visual studio不允许我这样做,因为引用已经以另一种方式进行,我也不能单独为资源制作另一个wpf应用程序,因为我会有一个我永远不会使用的窗口.. .
【解决方案2】:

您的项目将使用公共资源字符串似乎将使用 WPF 技术实现。在这种情况下,您可以稍微更改 xml 的格式并直接拥有一个包含 ResourceDictionary 的序列化形式的 xaml 文件。之后,您可以反序列化您的文件,并且您有一个 ResourceDictionary。可以使用 XamlWriter 和 XamlReader 完成序列化和反序列化。

代码示例:

        var pc = new ParserContext
        {
            BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
        };
        ...
        using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
        {
            try
            {
                var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
                if (resourceDictionary != null)
                {
                    Resources.MergedDictionaries.Add(resourceDictionary);
                }
            }
            catch
            {
                MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
            }
        }
    }

【讨论】:

    【解决方案3】:

    F# 项目中的工具不太好,所以我在my previous answer 中的建议将不起作用。
    在 C# 项目中,有一个名为“ResXFileCodeGenerator”的自定义工具(在构建之前)在 .resx 文件上运行并生成 C# 包装类。这显然在 F# 项目中不可用。你必须解决方法。
    我想到的最简单的方法——也就是说,如果你想使用从 C# 自定义工具生成的强类型包装器——是将新的 C# 类库添加到你的解决方案中,它将包含 resx 文件并将生成包装器类.您可以从 Project -> Add New Item... -> Resource File 添加 .resx 文件。然后,您可以从所有 F# 项目中引用此库并使用生成的包装类:

    open ClassLibrary1; // this is the C# library
    ...
    let x = Resources.String1;
    

    第二种方法是将 .resx 文件直接添加到您的 F# 项目中。有趣的是,Visual Studio 不允许您“添加新项目”类型为 Resource。您可以通过在另一个临时项目(例如类型 C# 类库)中创建资源文件来解决此问题,然后使用 Project -> Add Existing Item 命令将生成的 .resx 文件添加到您的 F# 项目中。然后,您可以使用 ResourceManager 类使用 resx 文件中的资源(当然没有为每个资源生成的属性,如前一种情况):

    open Library1
    open System.Resources
    
    [<EntryPoint>]
    let main argv = 
    // We are in the console application, which references Library1
    // Library1 contains the .resx file.
    
    let resourceManager = ResourceManager("Resources", typeof<Library1.Class1>.Assembly);
    
    let x = resourceManager.GetString("String1");
    
    0 
    

    请注意,在大写的情况下,我已将资源文件直接添加到项目中(而不是在 subfloder 中),作为名为 Resources.resx 的文件。
    您还可以创建自定义包装器,将此类调用封装在属性中。

    【讨论】:

    • 为什么我不能只引用我从 xml 文件创建的对象?我的意思是它应该足够简单,只需将字符串调用到 wpf 项目中,从而为我节省大量重做...
    【解决方案4】:

    结果我设法做了一些我想要的工作,但我没有使用反序列化的对象,而是使用了 xml 文件本身。

    这就是我所做的:

    首先,我通过 Right-click the file -&gt; Properties -&gt; Build Action -&gt; Resource 将 XML 文件的 Build ActionContent 更改为 Resource

    然后我进入Xaml文件,将以下内容添加到Window.Resources

    <XmlDataProvider 
        x:Key="DropDownData" 
        Source="/Resource;component/Strings.xml" 
        XPath="/Strings/String" />
    

    在我需要的字符串的下拉菜单中,我添加了这个:

    ItemsSource="{Binding Source={StaticResource DropDownData}}"
    

    现在我的字符串在 WPF gui 中显示得很漂亮。

    感谢您的建议;它们将来可能会派上用场。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 2023-03-25
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多