如何将用户控件更改为用户控件?

Posted

技术标签:

【中文标题】如何将用户控件更改为用户控件?【英文标题】:how to change user control to user control? 【发布时间】:2021-07-08 15:52:00 【问题描述】:

我有 2 个用户控件。 1 - 登录UC。 2 - 注册 uc。

登录用户控制:

<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>

注册用户控件:

<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>

我的引导程序:

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);
        
    

还有一个窗口,我想在其中更改这些用户控件:

<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);
        
    

如何点击登录用户控件中的注册按钮,将其更改为注册用户控件?,当您单击注册用户控件中的注册按钮时,将注册更改回登录?

我是这样做的:

更新

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】:

例如,您可以使用event aggreator 将事件或消息从视图模型发送到外壳。

这个想法是ShellViewModel通过激活视图来处理事件:

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;
    

LoginViewModelRegisterViewModel 类发布事件,例如:

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

【讨论】:

我的用户控件应该继承自 ChangeViewMessage 吗?我有点不明白,但这种方法绝对是优雅的。 我添加了代码,但是在视图中写道我找不到这样的视图。未找到 Program.ChangeViewMessage.View。 不,ChangeViewMessage 是您需要自己创建的自定义类。您可以在答案中复制我的示例类。 非常感谢。我做了,但我不知道多少是正确的)

以上是关于如何将用户控件更改为用户控件?的主要内容,如果未能解决你的问题,请参考以下文章

UWP 从 TemplateSelector 更改为用户控件不再显示绑定

DataGridView如何通过按下escape来检测用户何时从编辑控件中出来?

当用户将鼠标悬停在 TreeView 控件的特定 TreeNode 控件上时显示不同的光标

VS2012 - 将WPF现有用户控件添加到项目中

C# WPF 可拖动用户控件在 Canvas 上的 ListBox 中

如何引用VB6.0编 用户自定义控件