Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Screens and Conductors page on Wiki to document ConductWith #96

Open
KeithSwanger opened this issue Jan 2, 2020 · 3 comments
Open

Comments

@KeithSwanger
Copy link

I am attempting to use Conductor.Collection.AllActive to house multiple unique UserControls within one screen.

When binding to the Items collection of a conductor, how can I specify which VM will be used in a ContentControl?

This seems to work:
<ContentControl s:View.Model="{Binding Items[0]}" />

However, when I close the screen, I get this error:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'IScreen') from 'Items' (type 'BindableCollection`1'). BindingExpression:Path=Items[0]; DataItem='MainViewModel' (HashCode=48883615); target element is 'ContentControl' (Name=''); target property is 'Model' (type 'Object') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index'

My assessment from the error is that the VM is being deleted before the View, and it's trying to directly access an array element that doesn't exist any more. I don't get a crash, just an error in the console.

My main view is a UserControl split into sections which each house its own UserControl. I want to be able to specify which Item from the Conductor's Items collection each UserControl uses. Is there a better/safer way than accessing the Items collection at a specific element?

@canton7
Copy link
Owner

canton7 commented Jan 2, 2020

I think your assessment is correct.

If you're not binding Items to an ItemsControl (and you're instead binding UI controls to specific child VMs), I wouldn't bother with a conductor. I'd do:

public class MainViewModel : Screen
{
    public SomeViewModel SomeViewModel { get; }
    public OtherViewModel OtherViewModel { get; }

    public MainViewModel(...)
    {
        SomeViewModel = ...;
        SomeViewModel.ConductWith(this);

        OtherViewModel = ...;
        OtherViewModel.ConductWith(this);
    }
}

Then bind directly to SomeViewModel and OtherViewModel.

Conductors are useful when the set of children can change over time. If there is a static set of children, ConductWith is fine.

@KeithSwanger
Copy link
Author

Oh, that's beautiful. It works perfectly.

This might be worth mentioning on the Conductors wiki page, because wow, that is so useful.

Thank you for this awesome framework!

@canton7
Copy link
Owner

canton7 commented Jan 2, 2020

That's fair, I'll update the wiki page.

(That particular bit of functionality was copied from Caliburn.Micro)

@canton7 canton7 reopened this Jan 2, 2020
@canton7 canton7 changed the title Using Conductor<IScreen>.Collection.AllActive for multiple unique user controls Update Screens and Conductors page on Wiki to document ConductWith Jan 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants