DesignTime support bindings getting weird #359

Closed
beachwalker opened this Issue Aug 24, 2016 · 11 comments

Projects

None yet

3 participants

@beachwalker

I have an application that is split up in several libraries (containing views and models). However, the execution of the application is ok. This is the simple test result:

image

This shows a Container that has a property containing another Screen that needs to be resolved at runtime.

I have added two DesignTime ViewModels (one for Child and one for Container).

public class DesignContainerViewModel : Screen, IContainerViewModel
{
    public DesignContainerViewModel()
    {
        this.Text = "DesignTime Container";
        this.Child = new DesignChildViewModel(); // adding another DesignTimeViewModel manually
    }

    public string Text { get; set; }

    public IScreen Child { get; set; }
}

When selecting the ChildView everything seems to work:

image

When selecting the Container (with the ChildView inside):

image

The DesignViewModel for the Child can't be resolved to the corresponding View. Sounds ok, cause there is no existing mapping (have to figure out how to replace "DesignTime" in namespace and "Design" in ViewModel name... however if I change the code above to contain the real model instead of the DesignTimeViewModel:

public class DesignContainerViewModel : Screen, IContainerViewModel
{
    public DesignContainerViewModel()
    {
        this.Text = "DesignTime Container";
        this.Child = new ChildViewModel(); // using real model in designtimeviewmodel now
    }

    public string Text { get; set; }

    public IScreen Child { get; set; }
}

... it looks like this:

image

nice... BUT WAIT... there is something wrong. There is written "DesignTime Container" in both labels but there should be "DesignTime Child" in the lower one.

public class DesignChildViewModel : Screen, IChildViewModel
{
    private readonly string text;

    public DesignChildViewModel()
    {
        this.text = "DesignTime Child"; // not shown!?
    }

    public string Text
    {
        get
        {
            return this.text;
        }
    }
}

I use VS 2013 and WPF for this. This is the sample to reproduce this behavior.
CaliburnMicroDesignTimeSupport.zip

@beachwalker beachwalker changed the title from DesignTime support bindings getting weired to DesignTime support bindings getting weird Aug 24, 2016
@beachwalker
beachwalker commented Aug 24, 2016 edited

When I change the code of the DesignTimeViewModels slightly and use OnViewAttached overrides like this:

    protected override void OnViewAttached(object view, object context)
    {
        base.OnViewAttached(view, context);
        this.Child = new ChildViewModel();
    }

... the complete Designer of VS2013 gets broken when displaying the ContainerView (VS app is hanging and needs to be killedin the taskmanager). Here is the changed code to reproduce this:

CaliburnMicroDesignTimeSupportVSkiller.zip

@beachwalker
beachwalker commented Aug 24, 2016 edited

Maybe the following is more like a feature requres / improval:

I find it reasonable not using "real" ViewModels in other DesignTime ViewModels and use their DesignTime counterparts to keep dependencies cleaner. Maybe others do... Anyway, I think, it should be a default convenient mapping hat DesignTimeViewModels should be resolved to their ViewModel counterpart Views, too.
This can be by default like this:

SomeNamespace.SomeViewModel => SomeNamespace.DesignTimeSomeViewModel => SomeNamespace.SomeView
SomeNamespace.SomeViewModel => SomeNamespace.DesignTime.SomeViewModel => SomeNamespace.SomeView
SomeNamespace.SomeViewModel => SomeNamespace.DesignTime.DesignTimeSomeViewModel => SomeNamespace.SomeView
SomeNamespace.SomeViewModel => SomeNamespace.SomeDesignTimeViewModel => SomeNamespace.SomeView
SomeNamespace.SomeViewModel => SomeNamespace.DesignTime.SomeDesignTimeViewModel => SomeNamespace.SomeView

Maybe it is a good Idea to have something like ViewLocator.DesignNameTransformer.AddRule...
or DesignViewLocator.NameTransformer?

@beachwalker

When I change the name of the Text property for the ChildViewModel (from Text to OtherText

public interface IChildViewModel : IScreen
{
    string OtherText { get; } // name was Text before
}

... and updated the Binding in the ChildView

<Grid>
        <Label Content="{Binding OtherText}"></Label>
</Grid>

... the Label is not shown anymore. Maybe another explicit way is required to set to the right DataContext? But this seems Caliburn.Micro specific problem or not?

image

@beachwalker

This sample is the same as before but uses Autofac as IoC-Container. Everything else shows the same behaviour as with the examples before. This is set to have different names for the Text Property so there is no "lucky" match between parent and child property name.

CaliburnMicroDesignTimeSupportWithAutofac.zip

@eogas
eogas commented Oct 13, 2016

I think I've run into (essentially) this same issue. I have created a really basic reproducer here: https://github.com/eogas/CaliburnMicroDesignTimeNestedBindingBug

Basically it's just a root window that contains a child view, which itself contains another child view. It takes a bit of building to get the XAML window to render everything, but once it's stable, this is what I see.

ChildItemView

image

ItemView

image

ShellView

image

ItemView is able to render ChildItemView correctly as far as the hardcoded portions are concerned, however it doesn't render the bindings to ChildItemViewModel. Similarly, in ShellView, we can see the hardcoded portions of ItemView, but its bindings, including the ChildItemView, are not resolved at design time.

But everything works fine at runtime:
image

@eogas
eogas commented Oct 13, 2016

Is this the same issue as #214 ?

@beachwalker

At least it seems very similar. I had the issues with Vs2013 but Vs2015 was not yet tested by myself together with Cm. The described behavior makes it somewhat uncomfortable and difficult to build more complex applications. This is why I decided to upload the example with classes spread over different assemblies. Most Caliburn examples are somewhat simple and everything is in one single assembly... but that is not the case in most real life apps. Hope the attached example will help to find and solve the problem.

@beachwalker

Oh, this is indeed a duplicate of a one year old bug that is still there... #214

@nigel-sampson
Contributor

The fix related to #379 should resolve it.

In terms of design time naming conventions is certainly an interesting idea that's worth pursuing if you want to discuss it further.

@nigel-sampson nigel-sampson added the bug label Nov 9, 2016
@nigel-sampson nigel-sampson added this to the v3.0.2 milestone Nov 9, 2016
@beachwalker
beachwalker commented Nov 9, 2016 edited

Yes, it would be nice if Caliburn.Micro would support design time naming conventions. Should we open up a separate issue for that? For sure I would give more detailed input if needed.

@nigel-sampson
Contributor

@superware has created #388 to discuss it, feel free to add your ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment