So instanziieren Sie die Steuerung programmgesteuert in Catel

Ich versuche, Steuerelemente dynamisch zu erstellen und in ein Datenfenster zu laden.

Oben befinden sich Registerkarten mit verschiedenen Arten von Berichten. Ich möchte in der Lage sein, neue Berichte zu erstellen, ohne daran denken zu müssen, sie dem Registersteuerelement hinzuzufügen. Ich versuche dies mit einer Factory zu tun und benutze Reflektion, um Ansichten zu identifizieren, die eine bestimmte Schnittstelle implementieren. Sobald die Steuerelemente instanziiert sind (Code unten), möchte ich sie in ein TabItem einschließen und sie meinem Tab-Steuerelement hinzufügen. Hier ist die Fabrik:

class ReportHandlerFactory : IReportHandlerFactory
{
    private static IList<IReportControl> ReportHandlers;

    public IEnumerable<IReportControl> GetReportHandlers()
    {
        if (null == ReportHandlers)
        {
            ReportHandlers = LoadHandlers() ?? new List<IReportControl>();

            if (ReportHandlers.Count < 1)
            {
                ReportHandlers.Add(new DefaultReportControl());
            }
        }

        return ReportHandlers;
    }

    private static IList<IReportControl> LoadHandlers()
    {
        return (from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.GetInterfaces().Contains(typeof(IReportControl))
                      && !t.IsAbstract
                      && !(t.IsEquivalentTo(typeof(DefaultReportControl)))
                select (IReportControl)Activator.CreateInstance(t)
                   ).ToList<IReportControl>();
    }

    public class DefaultReportControl : TabItem, IReportControl
    {
        public DefaultReportControl() : base()
        {
            Header = "Error";
            Content = "No Reports Found.";
        }

        public new string Header
        {
            get { return base.Header.ToString(); }
            private set { base.Header = value; }
        }

        public IReportHandler ReportHandler
        {
            get { throw new Exception("No Handler Available for Default Report Control."); }
        }
    }

Hier ist mein MainViewDataWindow:

<mvvm:DataWindow x:Class="Petersco.Reports.Views.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:winForms="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"
    xmlns:mvvm="clr-namespace:Catel.Windows;assembly=Catel.MVVM"
    xmlns:views="clr-namespace:Petersco.Reports.Views"
    xmlns:catel="http://catel.codeplex.com"
    ShowInTaskbar="True" ResizeMode="CanResize" Icon="../Images/Icons/favicon.ico"
    Title="PCL Reports" MinHeight="768" MinWidth="1024">
<Grid Loaded="Grid_Loaded">

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="1*"/>
    </Grid.RowDefinitions>

    <TabControl Grid.Row="0" Margin="10,10,10,0" SelectedItem="{Binding SelectedReportTabItem}" 
                ItemsSource="{Binding ReportTabItems}" />
    <Button Grid.Row="1" Margin="0,5,10,10" Width="75"
                Content="Run Report" Command="{Binding RunReport}"
                HorizontalAlignment="Right" />
    <WindowsFormsHost Grid.Row="2" Margin="10,0,10,10">
        <winForms:ReportViewer x:Name="_reportViewer"/>
    </WindowsFormsHost>
</Grid>

Hier ist das ViewModel:

public class MainWindowViewModel : ViewModelBase
{
    private readonly IReportHandlerFactory _reportHandlerFactory;

    public MainWindowViewModel(IMessageMediator messageMediator,
                               IReportHandlerFactory reportHandlerFactory) : base(messageMediator)
    {
        Argument.IsNotNull(() => reportHandlerFactory);
        _reportHandlerFactory = reportHandlerFactory;

        ReportTabItems = new ObservableCollection<TabItem>(
            _reportHandlerFactory.GetReportHandlers().Select(x =>
                                                             new TabItem
                                                             {
                                                                 Header = x.Header,
                                                                 Content = x
                                                             }
                )
            );
        SelectedReportTabItem = ReportTabItems[0];
        RunReport = new Command(ExecuteRunReport, CanExecuteRunReport);
    }

    private bool CanExecuteRunReport()
    {
        if (SelectedReportTabItem == null)
        {
            return false;
        }
        return SelectedReportTabItem != null && GetReportHandler().ReportHandler.CanExecuteConstruct();
    }

    private void ExecuteRunReport()
    {
        if (SelectedReportTabItem == null)
        {
            return;
        }
        WaitCursor.Show();
        GetReportHandler().ReportHandler.Construct(ReportControl);
        ReportControl.RefreshReport();
    }

    private IReportControl GetReportHandler()
    {
        return SelectedReportTabItem.Content as IReportControl;
    }

    public Command RunReport { get; set; }
    public ReportViewer ReportControl { get; set; }
    public TabItem SelectedReportTabItem { get; set; }
    public ObservableCollection<TabItem> ReportTabItems { get; set; } 
}

Das Problem ist, dass beim Instanziieren von Ansichten auf diese Weise beim Initialisieren des ViewModel nichts von der Magie von Catel passiert. Vielleicht gehe ich das nicht richtig an, aber gibt es in Catel eine Funktion / einen Helfer zum programmgesteuerten Laden / Initialisieren von Ansichten / Ansichtsmodellen?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage