C# 扩展WPF应用程序

C# 扩展WPF应用程序,c#,wpf,mvvm,mef,C#,Wpf,Mvvm,Mef,我有一个WPF MVVM应用程序。我的一个视图有一个用户控件,每个安装都需要自定义该控件。它基本上是客户安装的草图,带有一些绑定到viewmodel的标签等 现在我的问题是,每个站点/安装的用户控件都不同。一种方法是使用xaml读取器从文件/数据库运行时加载xaml。这是可行的,但由于我的viewmodel是泛型的,所以我必须绑定到方法而不是属性,并且我无法使用objectdataprovider加载xaml 目前,我正在尝试查看是否可以使用MEF,以便将用户控件创建为插件。所以我现在要找的是:

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

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

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

  • 如何使用视图/视图模型定义为MEF导出协定的用户控件
  • 我的父视图(在我的wpf应用程序中)如何加载导入的用户控件
  • 感谢您提供任何建议,或者可能有人有不同的方法?

    我建议您与MEF结合使用。它有一个模块(您案例中的插件)和区域(动态加载视图的机制)的概念

    您将能够使用简单属性导出视图:

    [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}"/>
    
    
    
    我建议您考虑与MEF结合使用。它有一个模块(您案例中的插件)和区域(动态加载视图的机制)的概念

    您将能够使用简单属性导出视图:

    [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}"/>
    
    
    
    我想考虑的是一个设计,您需要为每个安装安装一个自定义视图。相反,我希望使这种观点更加通用。从长远来看,这将使您的设计更加简单。另外,您正在为维护噩梦做准备,每个安装群都有不同的安装

    从您的描述中有点难以区分,但听起来视图是某种对象的集合(某种带有标签的图形或其他东西)。因此,我会这样对待它

    我将创建一个基本抽象类,该类描述视图可以显示的每个对象。由于我没有更多的信息,我将把它称为“DrawingObject”,因为没有更好的术语。此类将保存视图中所有对象的所有公共信息。请注意,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将使用基类拥有这些对象的集合。该集合可能是私有的,因为您可能会从构造函数中的某个位置获取对象(即数据库、平面文件或…)

    类视图模型:ObservableItem
    {
    public ViewModel():base()
    {
    //调用某个对象以填充DrawingObjects属性
    填充的绘图对象();
    }
    ObservableCollection mDrawingObjects=
    新的可观察集合();
    公共可观测集合绘图对象
    {
    获取{return mDrawingObjects;}
    私有集{mDrawingObjects=value;}
    }
    }
    
    然后,您的视图将绑定到此集合并适当地绘制它们(我将留给实现者作为练习)

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


    显然,这是一个粗略的设计草图,可能有几个错误(我是从我的头脑中做的),但希望它足够继续下去

    >我想考虑的是您需要为每个安装安装自定义视图的设计。相反,我希望使这种观点更加通用。从长远来看,这将使您的设计更加简单。另外,您正在为维护噩梦做准备,每个安装群都有不同的安装

    从您的描述中有点难以区分,但听起来视图是某种对象的集合(某种带有标签的图形或其他东西)。因此,我会这样对待它

    我将创建一个基本抽象类,该类描述视图可以显示的每个对象。由于我没有更多的信息,我将把它称为“DrawingObject”,因为没有更好的术语。此类将保存视图中所有对象的所有公共信息。请注意,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将使用基类拥有这些对象的集合。该集合可能是私有的,因为您可能会从构造函数中的某个位置获取对象(即数据库、平面文件或…)

    类视图模型:ObservableItem
    {
    public ViewModel():base()
    {
    //调用某个对象以填充DrawingObjects属性
    填充的绘图对象();
    }
    ObservableCollection mDrawingObjects=
    新的可观察集合();
    公共可观测集合绘图对象
    {
    获取{return mDrawingObjects;}
    私有集{mDrawingObjects=value;}
    }
    }
    
    然后,您的视图将绑定到此集合并适当地绘制它们(我将留给实现者作为练习)

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


    显然,这是一个粗略的设计草图,可能有几个错误(我是从我的头脑中做的),但希望它足够继续下去

    我不理解这样的评论:“因为我的viewmodel是泛型的,所以我必须绑定到方法而不是属性。”