在不依赖App.xaml

时间:2018-02-03 16:18:22

标签: c# wpf resources mvvm-light

我将应用程序转换为DLL库,其中我的主窗口成为用户控件。我正在使用手动创建System.Windows.Application对象的方法来存储我的资源,但我希望远离它并让我的用户控件自给自足,所以我可以简单地执行以下操作:

CustomUserControl control = new CustomUserControl ( object_to_pass);

然后在内部处理其他所有事情。控件的基本布局是一个托管多个页面的框架,如向导式应用程序。

我有两个主要问题:

设置对视图模型的引用

我认为不是使用我广泛使用的System.Windows.Application.FindResource,而是在用户控件类上使用类似的函数,并通过单例传递对用户控件的引用。

为此,我在名为' ViewModelLocator'的类中使用mvvm-light的SimpleIoc容器。跟踪所有视图模型。问题是,这是从用户控件的datacontext绑定加载的App.xaml中的资源。

这不能再做了,因为用户控件本身必须在其自己的xaml中进一步实例化包含它的资源:

<UserControl x:Class="WUP.Views.WarmUpPluginUserControl"
        mc:Ignorable="d"
        ...
        ...
        <!--This will not work-->
        DataContext="{Binding Source={StaticResource Locator}, Path=MainWindowLogic}">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Path/To/ViewModelLocator/Resource.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

现在我必须在后面的用户控制代码中实例化ViewModel定位器,并将其设置为Resources.Add的资源。这迫使我从所有其他视图(Pages)切换到ViewModel定位器的所有引用的动态资源。这不仅会导致进一步描述的问题,而且丑陋,因为我无法再使用以前的路径访问成员函数:

DataContext="{Binding Source={StaticResource Locator}, Path=MainWindowLogic}">

引用xaml中的资源,动态与静态

我使用的资源是画笔,颜色,模板和转换器,每个都在自己的资源字典中,我按正确的顺序添加它们以避免依赖性问题。

第一部分中的方法可以通过引用单例中的用户控件从ViewModel访问资源。现在的问题是如何在应用程序的每个视图中加载资源。我尝试了将它们全部粘贴在Page.ResourcesUseControl.Resources中的强力方法,但这给了我一些页面中找不到资源的错误,尽管它们存在于那里。我正在调查为什么会发生这种情况,但我不确定

然后我尝试了创建单例类的Dr.WPF's方法,您可以使用该方法创建单个资源实例并将它们作为依赖属性公开。这迫使我再次使用动态资源来查看所有视图。

除了转换器之外,这对我的所有资源都很好,并且我最初以这种方式引用的所有转换器都会出错:

Visibility="{Binding Functions.DictatesActions, Converter={StaticResource BooleanToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}"

所以我不知道如何处理这是动态情景。

我正在考虑放弃这种方法,只使用System.Windows.Application来存储我的所有资源,尽管它可能会导致托管应用程序中的其他用户控件出现问题(winforms)。如果有更好的方法,请告诉我!

1 个答案:

答案 0 :(得分:0)

我终于设法解决了我的问题:

设置对视图模型的引用

在这里,我只需要从后面的代码中完成所有操作。正如我所提到的,我使用ViewModelLocator来跟踪我的所有虚拟机,因此我将引用设置为实际用户控件构造函数中的资源:

Resources["Start"] = view_model_locator.Start;
Resources["SelectUnit"] = view_model_locator.SelectUnit;
Resources["HardwareChecks"]  = view_model_locator.HardwareChecks;
Resources["ConfigurationChecks"] = view_model_locator.ConfigurationChecks;
...

然后我在ViewModel定位器中将对用户控件的引用包含为static属性:

ViewModelLocator.WarmUpPluginUserControl = this;

然后我可以在其代码中的其他视图中访问它,如下所示:

DataContext = ViewModelLocator.WarmUpPluginUserControl.FindResource("Start");     

我也可以在VM中使用它,就像我使用Application.Current.FindResource()一样。这不是最优雅的解决方案,但它有效

引用xaml中的资源,动态与静态

在这里,我坚持使用强力方法将所有资源都包含在每个页面的顶部:

<WUP:WUPPage.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/WarmUpPlugin;component/Resources/Colors.xaml"/>
            <ResourceDictionary Source="pack://application:,,,/WarmUpPlugin;component/Resources/Styles.xaml"/>
            ...
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

这确实给我带来了问题,因为我发现资源没有发现错误,但这是因为我的一些字典有其他依赖,所以我不得不通过MergedDictionaries将它们添加到相关的字典中。

当应用程序是独立的时,我没有注意到这个依赖性问题,因为所有必需的资源都已经加载到应用程序范围内。

我打算用Dr WPF方法替换它,但我仍然需要将所有我的XAML引用从static更改为动态,然后处理无法通过动态资源引用访问的转换器。