Расширение приложения WPF - PullRequest
       8

Расширение приложения WPF

0 голосов
/ 03 февраля 2011

У меня есть приложение WPF MVVM.Одно из моих представлений имеет пользовательский элемент управления, который должен быть настраиваемым для каждой установки.Это в основном эскиз установки клиента с некоторыми ярлыками и т. Д., Привязанными к модели представления.

Теперь моя проблема заключается в том, что этот пользовательский элемент управления отличается на каждом сайте / установке.Один из подходов заключается в загрузке xaml из среды выполнения файла / базы данных с использованием программы чтения xaml.Это работает, но так как моя view-модель является универсальной, мне нужно привязать методы, а не свойства, и я не могу загрузить xaml с помощью objectdataprovider.

В настоящее время я пытаюсь выяснить, можно ли использовать MEF, чтобыЯ могу создать пользовательский элемент управления как плагин.Итак, что я сейчас ищу, так это:

  1. как я могу определить пользовательский элемент управления с моделью представления / представления, которая экспортирует контракт для MEF
  2. Как может быть мое родительское представление (в моем приложении wpf) загрузить импортированный пользовательский элемент управления

Любые советы приветствуются, или, может быть, у кого-то другой подход?

Ответы [ 2 ]

3 голосов
/ 03 февраля 2011

Я предлагаю вам взглянуть на Prism в сочетании с 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}"/>
0 голосов
/ 03 февраля 2011

Одна вещь, которую я бы рассмотрел, - это дизайн, в котором вам нужно установить пользовательский вид для каждой установки. Вместо этого я хотел бы сделать это представление более общим. Это сделает ваш дизайн более простым в долгосрочной перспективе. Кроме того, вы настраиваете на кошмар обслуживания с другой установкой для каждой установленной базы.

Это немного сложно понять из вашего описания, но звучит так, будто представление - это коллекция какого-то объекта (какой-то рисунок с меткой или что-то в этом роде). Поэтому я бы отнесся к этому как таковому.

Я бы создал базовый абстрактный класс, который описывает, что может показать каждый объект, который может отображать ваш вид. Поскольку у меня нет больше информации, я назову эту вещь «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 будет тогда просто иметь коллекцию этих объектов, используя базовый класс. Набор может быть закрытым, потому что вы, вероятно, получите объекты из какого-либо места в конструкторе (например, из базы данных, или из простого файла, или ...)

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 может потребоваться реализовать соответствующие функции сериализации.

Очевидно, это грубый набросок дизайна, и может иметь пару ошибок (я сделал это из головы), но, надеюсь, этого достаточно, чтобы продолжить.

...