Search code examples
c#.netwpfxamlcaliburn.micro

How to deactivate an item in when Conductor Collection is set to AllActive


I am having trouble deactivating a ViewModel that is defined already in a ContentControl tag. I don't want to set Visibility to false, as this seems to be an inappropriate solution.

This is what it looks like and it seems that in AllActive, we don't need to activate each item:

<ContentControl Grid.Column="0" cal:View.Model="{Binding RandomScreenViewModel}"/>

This is what it looks like during "OneActive" mode for Conductor. Then we can call ActivateItem and DeactivateItem where Deactivate will actually close the Content:

<ContentControl Grid.Column="0" x:Name="ActiveItem"}"/>

I want the Activated item do close during AllActive. Is that even possible? In my opinion, it should be possible to remove an item from AllActive.

I am kinda n00b on using Conductors, so I hope anyone can help me with this. :D

ShellView.xaml:

Window x:Class="SimpleConductorOneActive.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.caliburnproject.org"
        xmlns:local="clr-namespace:SimpleConductorOneActive.ViewModels"
        Title="MainWindow" Height="350" Width="550" Background="CornflowerBlue">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <Button Content="New Screen" x:Name="NewScreen" />
            <TextBlock Text="Current Screen Count:" VerticalAlignment="Center" Padding="10,5,2,5"/>
            <TextBlock Text="{Binding Items.Count}" VerticalAlignment="Center" Padding="0,5,5,5"/>
        </StackPanel>
        <ContentControl Grid.Row="1" cal:View.Model="{Binding RandomScreenViewModel}" HorizontalAlignment="Center"  VerticalAlignment="Center"  Height="200" Width="180" Margin="342,0,20,10" Padding="5"/>

        <ListBox x:Name='Items' Grid.Row="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" Width="60" Margin="5">
                        <TextBlock Text="Screen Id" FontWeight="Bold"  />
                        <TextBlock Text='{Binding DisplayName}'  
                                   Margin='5 5 5 5'   
                                   Padding="5 5 5 5"
                                   FontSize='12' 
                                   TextWrapping="NoWrap"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation='Horizontal' />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>

    </Grid>
</Window>

ShellViewModel.cs:

public class ShellViewModel : Conductor<object>.Collection.AllActive
{

    public RandomScreenViewModel RandomScreenViewModel { get; set; }

    public int ScreenCount
    {
        get { return Items.Count; }
    }

    public ShellViewModel()
    {
        RandomScreenViewModel = new RandomScreenViewModel();
        NewScreen();
    }

    public void NewScreen()
    {
        ActivateItem(RandomScreenViewModel);
    }
}

RandomScreenView.xaml:

<UserControl x:Class="SimpleConductorOneActive.Views.RandomScreenView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Background="AliceBlue">
        <StackPanel Orientation="Vertical">
            <Button Content="Close" HorizontalAlignment="Right" Margin="5" x:Name="CloseScreen" />
            <TextBlock Text="Name:"/>
            <TextBlock x:Name="DisplayName"/>

        </StackPanel>
    </Grid>
</UserControl>

RandomScreenViewModel.cs:

   public class RandomScreenViewModel:Screen
    {
        public RandomScreenViewModel()
        {
            Guid id = Guid.NewGuid();
            DisplayName = id.ToString();
        }

        public void CloseScreen()
        {
            base.TryClose();
        }

    }

Solution

  • I'm new to WPF, Caliburn Micro and I've never used Conductor<T>.Collection.AllActivein real application but I've tried it a bit. When you add it to Items that is screen collection, All of it are activated.
    If you want do Deactivate it, you can simply use DeactivateItem(T item, bool close) method that take item you are conducting and bool indicate that you want to close it too.

    This is snippet of codes.

    ShellViewModel.cs

    public void Remove()
    {
        if (Items.Count > 0)
        {
            DeactivateItem(Items[0], true);
        }
    }
    

    ShellView.xaml

    <ItemsControl x:Name="Items" />
    <Button cal:Message.Attach="Remove"
            Width="50"
            Content="Deactive" />
    

    ShellView will get updated when item in Items was deleted as Items is type of IObservableCollection<T> that implement INotifyCollectionChanged I only tried to bind Items with ItemsControl but another control should be able to screen collection too(which I don't know XD)