how to change user control to user control?

247 Views Asked by At

I have 2 user controls. 1 - login uc. 2 - register uc.

Login user control:

<UserControl x:Class="Project.Views.LoginView"
        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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        mc:Ignorable="d"
        Width="350"
        Height="500">
    <Grid>
        <Rectangle Height="280" VerticalAlignment="Top">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="Aqua"/>
                    <GradientStop Color="#FF34268A" Offset="1"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

        <Rectangle Width="280" Height="240" VerticalAlignment="Bottom" Margin="0,80" RadiusY="10" RadiusX="10" Fill="White">
            <Rectangle.Effect>
                <DropShadowEffect BlurRadius="15" Direction="0" RenderingBias="Quality" ShadowDepth="1" Color="#FFBBBBBB"/>
            </Rectangle.Effect>
        </Rectangle>
        <Grid VerticalAlignment="Bottom" Margin="35,80" Height="240">
            <Label Content="Вход" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5" Foreground="Gray" FontSize="18"/>
            <StackPanel VerticalAlignment="Center" Margin="15">
                <TextBox x:Name="Username" materialDesign:HintAssist.Hint="Логин" Margin="0,10"  Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <PasswordBox x:Name="Password" materialDesign:HintAssist.Hint= "Пароль" Margin="0,10" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
            </StackPanel>
        </Grid>
        <Button x:Name="Login" Width="150" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,65" Content="Войти"/>
        <Button x:Name="Register" Width="150" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="5" Content="Register?" Background="{x:Null}"/>
        <Image Source="/Project;component/Assets/smartphone.png" Width="100" Height="100" VerticalAlignment="Top" Margin="30"/>
    </Grid>
</UserControl>

Register user control:

<UserControl x:Class="Project.Views.RegisterView"
             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" 
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             mc:Ignorable="d"
             Width="350"
             Height="800">
    <Grid>
        <Rectangle Height="280" VerticalAlignment="Top">
            <Rectangle.Fill>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="Aqua"/>
                    <GradientStop Color="#FF34268A" Offset="1"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

        <Rectangle Width="280" Height="500" VerticalAlignment="Bottom" Margin="0,80" RadiusY="10" RadiusX="10" Fill="White">
            <Rectangle.Effect>
                <DropShadowEffect BlurRadius="15" Direction="0" RenderingBias="Quality" ShadowDepth="1" Color="#FFBBBBBB"/>
            </Rectangle.Effect>
        </Rectangle>
        <Grid VerticalAlignment="Bottom" Margin="35,80" Height="500">
            <Label Content="Регистрация" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="5" Foreground="Gray" FontSize="18"/>
            <StackPanel VerticalAlignment="Center" Margin="15">
                <TextBox x:Name="Email" materialDesign:HintAssist.Hint="Email" Margin="0,10"  Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <PasswordBox x:Name="Password" materialDesign:HintAssist.Hint= "Пароль" Margin="0,10" Style="{StaticResource MaterialDesignFloatingHintPasswordBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <TextBox x:Name="Username" materialDesign:HintAssist.Hint="Имя" Margin="0,10"  Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <TextBox x:Name="Surname" materialDesign:HintAssist.Hint="Фамилия" Margin="0,10"  Style="{StaticResource MaterialDesignFloatingHintTextBox}" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <DatePicker x:Name="BirthdayDate" Margin="0,10" materialDesign:HintAssist.Hint="Выберите дату рождения" FontFamily="Champagne &amp; Limousines" FontSize="18"/>
                <Button x:Name="SelectPhoto" Content="Выбор фото"/>
            </StackPanel>
        </Grid>
        <Button x:Name="Register" Width="150" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,65" Content="Зарегистрироваться"/>
        <Image Source="/Project;component/Assets/smartphone.png" Width="100" Height="100" VerticalAlignment="Top" Margin="30"/>
    </Grid>
</UserControl>

My bootstrapper:

public class Bootstrapper : BootstrapperBase
    {
        private SimpleContainer _container = new SimpleContainer();
        public Bootstrapper()
        {
            Initialize();

            ConventionManager.AddElementConvention<PasswordBox>(
            PasswordBoxHelper.BoundPasswordProperty,
            "Password",
            "PasswordChanged");
        }
        protected override void Configure()
        {
            _container.Singleton<IWindowManager, WindowManager>();
            _container.Singleton<LoginViewModel>();
            _container.Singleton<RegisterViewModel>();
            _container.Singleton<HomeViewModel>();
            _container.Singleton<ShellViewModel>();
        }
        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<ShellViewModel>();
        }
        protected override object GetInstance(Type service, string key)
        {
            return _container.GetInstance(service, key);
        }
        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return _container.GetAllInstances(service);
        }
        protected override void BuildUp(object instance)
        {
            _container.BuildUp(instance);
        }
    }

And there is a window in which I want to change these user control:

<Window x:Class="Project.Views.ShellView"
        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:SocialNetwork.Views"
        mc:Ignorable="d"
        Width="350"
        Height="500">
    <Grid>
        <ContentControl x:Name="ActiveItem"/>
    </Grid>
</Window>

ShellViewModel:

public class ShellViewModel : Conductor<object>
    {
        private LoginViewModel _loginViewModel;
        private RegisterViewModel _registerViewModel;
        public ShellViewModel(LoginViewModel loginViewModel, RegisterViewModel registerViewModel)
        {
            DisplayName = "Войти";
            _loginViewModel = loginViewModel;
            _registerViewModel = registerViewModel;
            ActivateItemAsync(_loginViewModel);
        }
    }

How do I click on the Register button in login user control, change it to register user control?, and when you click on the Register button in register user control, change back register to login?

I did it like this:

Update

public Task HandleAsync(ChangeViewMessage message, CancellationToken cancellationToken)
        {
            if (message.ViewModelType.Name.Equals("LoginViewModel"))
            {
               DisplayName = "Регистрация";
               
               NotifyOfPropertyChange(() => DisplayName);
               return ActivateItemAsync(_registerViewModel);
            }
            else
            {
                DisplayName = "Вход";
                NotifyOfPropertyChange(() => DisplayName);
                return ActivateItemAsync(_loginViewModel);
            }
        }
1

There are 1 best solutions below

4
mm8 On BEST ANSWER

You could for example use the event aggreator to send an event or a message from the view model to the shell.

The idea is that the ShellViewModel handles the event by activating the view:

public class ShellViewModel : Conductor<object>, IHandle<ChangeViewMessage>
{
    public ShellViewModel(IEventAggregator eventAggregator)
    {
        eventAggregator.Subscribe(this);
        ...
    }

    public void Handle(ChangeViewMessage message)
    {
        // call ActivateItemAsync based on type here...
    }
    
    ...
}

public class ChangeViewMessage
{
    public readonly Type ViewModelType;

    public ChangeViewMessage(Type viewModelType)
    {
        ViewModelType = viewModelType;
    }
}

And the LoginViewModel and RegisterViewModel classes publish events, e.g.:

eventAggregator.Publish(new ChangeViewType(this.GetType()));