Martijn
Martijn

Reputation: 151

Can't use windowManager.ShowWindow() with Caliburn.Micro

I'm currently developing a plugin for Revit (BIM software) and I'm, trying to use WPF and Caliburn.Micro to show a window/dialog when I press a button of the plugin.

So like in the documentation, I have a bootstrapper:

public class Bootstrapper : BootstrapperBase
{

    public Bootstrapper()
    {
        Initialize();
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor<LocationPopupViewModel>();
    }
}
}

A simple testing ViewModel:

namespace ExternalForms.ViewModels
{

public class LocationPopupViewModel : Screen
{
    private int _horizontalLength;
    private int _verticalLength;

    public int HorizontalLength
    {
        get 
        { 
            return _horizontalLength; 
        }
        set 
        { 
            _horizontalLength = value;
            NotifyOfPropertyChange(() => HorizontalLength);
        }
    }

    public int VerticalLength
    {
        get 
        { 
            return _verticalLength; 
        }
        set 
        { 
            _verticalLength = value;
            NotifyOfPropertyChange(() => VerticalLength);
        }
    }
}
}

And of course the window that I want to show:

<Window x:Class="ExternalForms.Views.LocationPopupView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:ExternalForms.Views"
    mc:Ignorable="d" WindowStartupLocation="CenterScreen"
    ResizeMode="CanResizeWithGrip"
    Title="gebied" Height="300" Width="410"
    FontSize="16">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>


    <!--Row 1-->
    <TextBlock Text="Stel xxx in" FontWeight="DemiBold" Grid.Column="1" Grid.Row="1" FontSize="18"/>

    <!--Row 2-->
    <StackPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Width="360" Margin="0, 0, 0, 20">
        <TextBlock TextWrapping="Wrap">
            Let op dat het gebied een maximale horizontale en verticale lengte mag hebben van 1 kilometer.
        </TextBlock>
    </StackPanel>


    <!--Row 3-->
    <TextBlock Text="Horizontaal" Grid.Column="1" Grid.Row="3"/>

    <!--Row 4-->
    <TextBox x:Name="HorizontalLength" Grid.Row="4" Grid.Column="1" MinWidth="100"/>


    <!--Row 5-->
    <TextBlock Text="Verticaal" Grid.Column="1" Grid.Row="5"/>

    <!--Row 6-->
    <TextBox x:Name="VerticalLength" Grid.Row="6" Grid.Column="1" MinWidth="100"/>


    <!--Row 7-->
    <StackPanel Orientation="Horizontal" Grid.Row="7" Grid.Column="1" Margin="0, 20, 0, 0" Grid.ColumnSpan="2" HorizontalAlignment="Right">
        <Button x:Name="SubmitDimensions" IsDefault="True" Width="100" Height="30">OK</Button>
        <Button IsCancel="True" IsDefault="True" Width="100" Height="30">Cancel</Button>
    </StackPanel>

</Grid>

The function that is trying to show the window:

        private void SetBoundingBox()
    {
        IWindowManager windowManager = new WindowManager();

        LocationPopupView locationPopup = new LocationPopupView();

        windowManager.ShowWindow(locationPopup, null, null);

    }

But when I try to open the dialog in Revit, a window with an error pops up: enter image description here

UPDATE: My current project structure looks like this: enter image description here

Assembly "UI" takes care of all the internal UI elements in Revit (so the buttons in Revit, even though there is currently only one).

The current button in Revit calls the "Get3DBAG" assembly, who does some tasks and eventually calls the "Location" assembly, which calls the Windowmanager.showwindow() method for the WPF views, which are in the "ExternalForms" assembly.

Upvotes: 0

Views: 873

Answers (1)

Anu Viswan
Anu Viswan

Reputation: 18163

You problem lies in the following line.

LocationPopupView locationPopup = new LocationPopupView();

You are attemping to initialize an instance of View, instead of ViewModel. You should replace this with following.

LocationPopupViewModel locationPopup = new LocationPopupViewModel();

Caliburn Micro would resolve the corresponding View by itself using the naming convention.

Update : Based on Comment

From your comment, it looks like your View/ViewModels are in a different assembly. In that scenario, you need to ensure the assembly is included while Caliburn Micro searches for Views. You can do so by overriding SelectAssemblies method in Bootstrapper.

    protected override IEnumerable<Assembly> SelectAssemblies()
    {
        return new[] 
       {
           Assembly.GetExecutingAssembly()
          // Ensure your external assembly is included.
       };
    }

You would be also interested to read more Custom Conventions using Caliburn Micro

Upvotes: 0

Related Questions