如何在MVVM视图模型中指定资源? [英] How can I specify resources in an MVVM view model?

查看:104
本文介绍了如何在MVVM视图模型中指定资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想显示每个对象应该有一个名称和一个合适图像的对象列表(例如带有图标的MenuItems,或带有文本和图像的按钮)。

Suppose I want to show list of objects where each object should have a name and a suitable image (for example MenuItems with Icons, or buttons with text and image).

所有示例和程序都将viewmodel中的图像暴露为PNG文件的路径,然后绑定 Image Source $ c>到那。但是,如果我想在本地 ResourceDictionary 中使用矢量图像(例如 DrawingImage ),该怎么办?从视图模型中公开DrawingImage似乎很糟糕,因为我必须存储对应用程序/窗口/用户控件/ ...的引用(建议不要从视图模型中公开这样的XAML对象)。

All examples and programs exposed the image in the viewmodel as a path to a PNG file and then bound the Source of an Image to that. But what if I want to use vector images (for example as a DrawingImage in a local ResourceDictionary)? Exposing the DrawingImage from the view model seems bad because I would have to store a reference to the application/window/user control/... (and it is advised to not expose such XAML objects from view models).

因此,更好的方法是在视图模型中使用字符串标识符,然后以某种方式选择适当的资源。如果该标识符是资源键,则此代码段看起来很诱人但不起作用:

So a better approach would be to use a string identifier in the view model and then somehow select the appropriate resource. If that identifier is the resource key this snippet looks tempting but does not work:

<Image Source="{StaticResource {Binding Icon}}"/>

我找到了两个解决方法,虽然它们对我不起作用。

I found two workarounds for that though they did not work for me.


  1. 第一个使用正常绑定图标的转换器在 Application.Current 。如果资源存储在我认为的其他地方(并且我最初碰到这个问题的情况没有运行应用程序,因为它是一个Window选择要启动的应用程序!)。这不起作用。

  1. The first one was using a normal binding to the icon with a converter that looked up the resource in Application.Current. This does not work if the resource is stored somewhere else I think (and the situation where I initially bumped into this problem had no Application running yet since it was a Window choosing the Application to launch!).

第二种解决方法是使用从 StaticResourceExtension 派生的标记扩展,获取其 ResourceKey 来自传递的绑定:

The second workaround was using a markup extension derived from StaticResourceExtension that fetched its ResourceKey from the passed binding:

<Image Source="{local:BindableStaticResource {Binding Icon}"/>

这个看起来很整洁,因为它可以使用本地资源,也可以用于其他事情。但是在使用它时我总是遇到异常(无法找到名为{FooIcon}的资源。,显示正确的XAML文件和扩展名的位置)。即使是从 StaticResourceExtension 派生的空资源扩展,它只是将资源键传递给基础构造函数也不起作用,我无法解释原因。只需使用 StaticResourceExtension 就可以了。

This one looks really neat because it could use local resources, also be used for other things. But when using it I always got an exception ("Resource named {FooIcon} could not be found.", showing the correct XAML file and position of the extension). Even an empty resource extension derived from StaticResourceExtension that just passed the resource key to the base constructor did not work and I cannot explain why. Just using StaticResourceExtension worked just fine.

任何想法如何我可以修复第二种方法,甚至更好的解决方案?

Any ideas how I could fix the second approach, or even better solutions?

我注意到它

<Window>
    <Window.Resources>
        <DrawingImage x:Key="SomeIcon"/>
    </Window.Resources>
    <Image Source="{BindableStaticResource {Binding Icon}}"/>
</Window>

但例如在 DataTemplate 中失败。虽然普通的 StaticResourceExtension 在这两种情况下都能正常工作,所以我很困惑。

but fails for example in a DataTemplate. Though a normal StaticResourceExtension works on both occasions so I am puzzled what is going wrong.

推荐答案

您提到的第一个解决方法可以在这里找到:将datacontext字符串属性绑定到StaticResource键

The first workaround you mention can be found here: Binding a datacontext string property to a StaticResource key

我试图使用你提到的第二个工作( http://sweux.com/blogs /psampaio/index.php/2009/06/16/using-data-binding-with-static-resources-in-wpf/ ),但我从来没有工作过。由于DataContext为null,因此抛出了ArgumentNullException。我认为这与我使用DataTemplate从我的ViewModel创建View的事实有关,并且在调用ProvideValue方法之前没有设置DataContext(在该页面的示例中,DataContext设置在.xaml.vb类)。

I tried to use the second work around you mention ( http://sweux.com/blogs/psampaio/index.php/2009/06/16/using-data-binding-with-static-resources-in-wpf/), but I never got it working. It throwed an ArgumentNullException since the DataContext was null. I think this had something to do with the fact that I was using a DataTemplate to create my View from my ViewModel, and somehow the DataContext was not set before the ProvideValue method was called (in the example on that page, the DataContext is set in the .xaml.vb class).

所以,我开始寻找一个解决方法并找到一个也涉及转换器,但是这个通过FrameworkElement方法找到资源而不是在Application.Current周围。我找到的那个详细信息如下:

So, I started looking for a workaround and found one which also involves a converter, but this one finds the resource through a FrameworkElement method instead of poking around Application.Current. The one I found is detailed here:

http://drwpf.com/blog/2007/08/18/can-my-value-converter-access-the-绑定目标/

我将在此处复制相关信息:

I'll copy the relevant information here:

它涉及一个实现IMultiValueConverter接口的ValueConverter,可以访问设置绑定的控件。

It involves a ValueConverter implementing the interface IMultiValueConverter, to have access to the control on which the binding is set.

Convert方法的代码如下:

The code for the Convert method is the following:

public object Convert(object[] values, Type targetType, 
    object parameter, CultureInfo culture)
{
    FrameworkElement targetObject = values[0] as FrameworkElement;

    if (targetObject == null)
    {
        return DependencyProperty.UnsetValue;
    }
    return targetObject.TryFindResource(values[1]);
}

内容控件的XAML如下所示:

And the XAML for a content control would look like this:

<ContentControl>
  <ContentControl.Content>
    <MultiBinding Converter="{StaticResource Converter}">
      <MultiBinding.Bindings>
        <Binding RelativeSource="{RelativeSource Self}" />
        <Binding Path="ResourceKey" />
      </MultiBinding.Bindings>
    </MultiBinding>
  </ContentControl.Content>
</ContentControl>

图片的XAML如下:

<Image Height="16" Width="16">
    <Image.Source>
        <MultiBinding Converter="{StaticResource Converter}">
            <MultiBinding.Bindings>
                <Binding RelativeSource="{RelativeSource Self}" />
                <Binding Path="ResourceKey" />
            </MultiBinding.Bindings>
        </MultiBinding>
    </Image.Source>
</Image>

像魅力一样:D

这篇关于如何在MVVM视图模型中指定资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆