Laden...

Dynamisch Inhalte in MVVM/WPF mittels Plugins

Erstellt von JimStark vor 2 Jahren Letzter Beitrag vor 2 Jahren 1.188 Views
JimStark Themenstarter:in
309 Beiträge seit 2020
vor 2 Jahren
Dynamisch Inhalte in MVVM/WPF mittels Plugins

Vielleicht für Anfänger interessant, die eine Plugin-Engine für eine WPF-Anwendung bauen wollen und Inhalte dynamisch hinzufügen wollen:
MVVM siehe: [Artikel] MVVM und DataBinding
Das ganze ist natürlich stark vereinfacht und nutzt direkt das MainViewModel, was für aufwendigere Anwendungen wahrscheinlich ungeeignet ist.

Was sollen unsere Plugins wissen?


    public interface IHostView
    {
        public string WindowTitle { get; set; }
    }

Z.B. MainViewModel implementiert IHostView:


    public class MainViewModel : BaseViewModel, IHostView
    {
        private List<Plugin> _Plugins = new List<Plugin>() ;

        private string _WindowTitle = "Meine Hauptanwendung";
        public string WindowTitle { 
            get => _WindowTitle;
            set  {
                _WindowTitle = value;
                OnPropertyChanged(nameof(WindowTitle));
            }

        }
        public List<MenuItem> PluginMenuItems
        {
            get
            {
                var list = new List<MenuItem>();
                foreach (var plugin in _Plugins)
                    list.Add(plugin.GetPluginMenuItem());
                return list;
            }
        }

        public MainViewModel()
        {
            // Plugins dynamisch hinzufuegen
            _Plugins.Add(new MeinPlugin(this));
        }
    }

Abstrakte Plugin-Klasse, was soll es können:


    public abstract class Plugin
    {

        public IHostView _Host;
        public Plugin(IHostView host)
        {
            _Host = host;
        }

        public abstract string Name { get; }

        // Standardmaessig kein MenuItem
        public virtual MenuItem GetPluginMenuItem() { return null; }
    }

Plugin-Implementierung:


    public class MeinPlugin : Plugin
    {
        public MeinPlugin(IHostView host) : base(host)
        {
        }

        public override string Name => "Mein Plugin";

        public override MenuItem GetPluginMenuItem()
        {
            var menuItem = new MenuItem();
            // Alternativ Command
            menuItem.Header = this.Name;
            menuItem.Click += MenuItem_Click;
            return menuItem;
        }

        private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            _Host.WindowTitle = "Hallo !";
        }

Plugin Obermenü im Window:


...
        Title="{Binding WindowTitle}" Height="450" Width="800">
    <Window.DataContext>
        <vms:MainViewModel />
    </Window.DataContext>

        <Menu DockPanel.Dock="Top">
            <MenuItem Header="File">
                <MenuItem Header="Exit"/>

            </MenuItem>
            <MenuItem Header="Plugins" ItemsSource="{Binding PluginMenuItems}"/>
        </Menu>

Mittels ItemsControl könnte man auch Controls in verschiedenen Bereichen dynamisch hinzufügen, etc.