扩展WPF应用程序

时间:2011-02-03 09:32:14

标签: c# wpf mvvm mef

我有一个WPF MVVM应用程序。我的一个视图有一个用户控件,需要为每个安装自定义。它基本上是客户安装的草图,其中一些标签等绑定到视图模型。

现在我的问题是每个站点/安装的用户控件都不同。一种方法是使用xaml阅读器从文件/数据库运行时加载xaml。这是有效的,但由于我的viewmodel是通用的,我必须绑定到方法而不是属性,我无法加载带有objectdataprovider的xaml。

目前我正在尝试查看是否可以使用MEF以便我可以将用户控件创建为插件。所以我现在正在寻找的是:

  1. 如何使用导出MEF合同的视图/视图模型定义用户控件
  2. 我的父视图(在我的wpf应用程序中)如何加载导入的用户控件
  3. 任何提示都表示赞赏,或者有人采用不同的方法?

2 个答案:

答案 0 :(得分:3)

我建议你与MEF一起研究Prism。它有一个模块(在你的情况下是插件)和Regions(动态加载视图的机制)的概念。

您可以使用简单属性导出视图:

[ViewExport(RegionName = RegionNames.MyRegion)]
public partial class MyView : UserControl {
    public MyView() {
        this.InitializeComponent();
    }

    [Import]
    public MyViewModel ViewModel {
        set { DataContext = value; }
    }
}

[Export]
public class MyViewModel : ViewModelBase
[
  ...
}

在您的主应用程序XAML中,您将能够导入插件的视图,如下所示:

<ContentControl Regions:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.MyRegion}"/>

答案 1 :(得分:0)

我要考虑的一件事是您需要为每个安装安装自定义View的设计。相反,我希望使该视图更通用。从长远来看,这将使您的设计更加简单。此外,您正在为每个安装基础的不同安装设置维护噩梦。

从你的描述中说出来有点困难,但听起来像是某种物体的集合(某种带有标签的图画或其他东西)。因此,我会这样对待它。

我将创建一个基本抽象类,用于描述View可以显示的每个对象。由于我没有更多的信息,因为缺乏一个更好的术语,我会把这个东西称为“DrawingObject”。此类将包含View中所有对象的所有公共信息。请注意,ObservableItem是一个实现INotifyPropertyChanged的类,SetProperty设置该基类中的值并引发PropertyChanged。

abstract class DrawingObject : ObservableItem
{
    Point mPosition;
    public Point Position
    {
        get { return mPosition; }
        set { SetProperty("Position", ref mPosition, value); }
    }

    String mLabelText;
    public String LabelText
    {
        get { return mLabelText; }
        set { SetProperty("LabelText", ref mLabelText, value); }
    }
}

然后,从该基类派生更多自定义对象:

class Counter : DrawingObject
{
    public Counter() : base()
    {
    }
}

然后,您的ViewModel将使用基类拥有这些对象的集合。该集可能是私有的,因为您可能会从构造函数中的某个位置获取对象(即数据库,或平面文件,或......)

class ViewModel : ObservableItem
{

    public ViewModel() : base()
    {
        // Call something to populate DrawingObjects property
        PopulateDrawingObjects();
    }

    ObservableCollection<DrawingObject> mDrawingObjects = 
        new ObservableCollection<DrawingObject>();
    public ObservableCollection<DrawingObject> DrawingObjects
    {
        get { return mDrawingObjects; }
        private set { mDrawingObjects = value; }
    }
}

然后,你的View将绑定到这个集合并适当地绘制它们(我将把它作为实现者的练习)。

我没有展示的一个扩展是DrawingObject可能需要实现适当的序列化功能。

显然,这是设计的粗略草图,可能会有一些错误(我是从头开始做的),但希望它足以继续下去。