更改DocumentViewer的默认本地化错误消息

时间:2013-06-25 12:53:57

标签: c# .net

DocumentViewer WPF contorol正在使用System.Windows.SR.Get(string)内部方法来显示向用户进行搜索时显示的消息。即使我将pl-PL设置为CurrentCultureCurrentUICulture,这些也不是本地化的。

我已经调查过一点System.Windows.SR.Get(string)使用来自new ResourceManager("ExceptionStringTable", typeof (System.Windows.SR).Assembly)程序集的PresentationFramework,而ResourceManager程序集又会使用这些消息加载ExceptionStringTable.resources文件。据我所知,这是整个框架的标准本地化技术。

我的问题是:如何让WPF显示我的自定义本地化消息?我尝试过使用hacky反射,并且能够访问SR类的内部ResourceManager。我应该将它包装在我的自定义{{1}}实现中,还是有更简单的方法?

1 个答案:

答案 0 :(得分:1)

我决定参加反思黑客攻击。您必须在应用程序启动时使用此代码来交换内部.NET类ResourceDictionary中使用的SR

var assembly = typeof(DocumentViewer).Assembly;
var sr = assembly.GetType("System.Windows.SR");

var field = sr.GetField("_resourceManager", BindingFlags.NonPublic | BindingFlags.Static);


var resourceManager = (ResourceManager)field.GetValue(null);
var wrapper = new ResourceManagerWrapper(resourceManager);


wrapper.SetString("DocumentViewerSearchUpCompleteLabel", "test");
wrapper.SetString("DocumentViewerSearchDownCompleteLabel", "test");
wrapper.SetString("DocumentViewerSearchCompleteTitle", "test");
//And so on... you can find all those messages with dotPeek or similar tool in `DocumentViewer` implementation

field.SetValue(null, wrapper);

我将资源查找转发到ResourceManager的包装器类非常简单:

public class ResourceManagerWrapper : ResourceManager
{
    private Dictionary<string, string> local_ = new Dictionary<string,string>();
    private ResourceManager manager_;
    public ResourceManagerWrapper(ResourceManager manager)
    {
        this.manager_ = manager;
    }

    public override string GetString(string name)
    {
        string value;
        if(local_.TryGetValue(name, out value))
        {
            return value;
        }
        else
        {
            return manager_.GetString(name);
        }
    }

    public void SetString(string key, string value)
    {
        local_[key] = value;
    }
}