3

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

该程序的结构如下:

项目 A 引用B 和 C

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

项目 B 参考C

  • F# 中的 GUI 逻辑

项目 C

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

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

4

4 回答 4

1

我建议您使用内置的 .resx 文件,该文件默认包含在新创建的 WPF 应用程序中。 (您也可以在以后使用Project -> Add New Item... -> Resource File.
公共 Resx 文件
和其他资源!)通过一个强类型的自动生成的包装类:

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

您还可以使用 XAML 将属性设置为存储在此文件中的字符串,使用x:Static 标记扩展名,如(例如)此答案中所述:

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

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

于 2013-09-19T20:42:46.880 回答
0

从看起来你的项目将使用公共资源字符串将使用 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);
            }
        }
    }
于 2013-09-19T14:27:46.840 回答
0

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

于 2013-09-22T16:30:11.180 回答
0

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

这是我所做的:

首先,我将 XML 文件的Build ActionContent更改ResourceRight-click the file -> Properties -> Build Action -> Resource 构建操作菜单

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

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

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

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

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

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

于 2013-09-23T09:16:44.433 回答