ViewModel 能否通过 ResourceDictionary URI 保存视图的间接引用



WPF和MVVM就像身体和灵魂。对于ViewModel来说,忘记它可能连接到的View是有道理的(反之亦然)。

但是,在ViewModel中引用视图的资源字典甚至是一种罪过吗?这是否违背了目的?

例如,如果虚拟机可以通过资源字典保存视图引用,则以下代码用于 POC 目的。 ViewModel可以动态更改此资源字典(基于某些输入参数)。

我的视图模型.cs

   public interface IViewInjectingViewModel
   {
      void Initialize();
      URI ViewResourceDictionary { get; }
   }
   public class MyViewModel : IViewInjectingViewModel
   {
       private URI _viewResourceDictionary;
       public void Initialize()
       {
          _viewResourceDictionary = new URI("pack://application:,,,/MyApplication;component/Resources/MyApplicationViews.xaml");
        }
        public URI ViewResourceDictionary 
        {
           get
           {
              return _viewResourceDictionary;
           }
        }
   }

MyApplicationViews.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate DataType="{x:Type local:MyViewModel}">
    <StackPanel>
        <TextBlock 
        Text="Portfolios" FontFamily="Verdana" 
        FontSize="16" FontWeight="Bold" Margin="6,7,6,4"/>
        <ListBox 
        Margin="2,1" SelectionMode="Single" 
        ItemsSource="{Binding AvailableTraders}"
        SelectedItem="{Binding SelectedTrader}" DisplayMemberPath="Name">
        <!-- ... -->
        </ListBox>
    </StackPanel>
    </DataTemplate>
</ResourceDictionary>

MainWindow.xaml

<Window ...>
     <ContentControl 
    DataContext="{Binding myViewModel}"
    local:MyBehaviors.InjectView="true"/>
</Window>

常见行为:

public static class MyBehaviors
{
    public static readonly DependencyProperty InjectViewProperty 
        = DependencyProperty.RegisterAttached(..);
    //attached getters and setters...
    private static void OnInjectViewPropertyChanged(..)
    {
        var host = o as ContentControl;
        if ((bool)e.NewValue)
        {
            host.DataContextChanged
                += (o1, e1)  =>
                {
                    var viewInjectingVM = host.DataContext as IViewInjectingViewModel;
                    if (viewInjectingVM != null)
                    {
                        host.Resources.MergedDictionaries.Clear();
                        host.Resources.MergedDictionaries.Add( 
                            new ResourceDictionary() {    
                                Source = viewInjectingVM.ViewResourceDictionary 
                            });
                        host.Content = viewInjectingVM;
                    }
                };
        }
    }
}

好的,我来拍一张照片。 我认为这没关系。 如果您将视图模型视为表示层的一部分,那么让视图模型更改视图的资源字典以响应某些操作完全符合 MVVM 范例。

本质上,您正在更改视图的表示以响应某些操作,而视图模型对此负有此责任。 因此,在此上下文中更新资源字典在 MVVM 模式中似乎有效。

最新更新