如何在一个 xaml 页面中使用多个用户控件?

Posted

技术标签:

【中文标题】如何在一个 xaml 页面中使用多个用户控件?【英文标题】:How do I use multiple user-controls inside one xaml page? 【发布时间】:2019-09-26 21:40:55 【问题描述】:

我正在创建一个用于教育目的的应用程序。如何在“MainWindow.xaml”中使用多个用户控件?

我想在我的 MainWindow 上使用用户控件,这样我就不需要多个窗口。因此,在您在注册布局上按下一步后,

它应该带你到感谢屏幕,这也是另一个 UserControl 类。虽然在同一个窗口。

我已经阅读了尽可能多的不同“解决方案”,但没有任何真正的运气......

这是我的自动取款机代码。

主窗口.xaml

<Window x:Class="WpfApp1.MainWindow"
    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:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="700" Width="700"
    WindowStartupLocation="CenterScreen">

<Grid>
    <!--Background image-->
    <Grid.Background >
        <ImageBrush ImageSource="login-page-background-3.jpg"/>
    </Grid.Background>

    <!--Main content scroll-->
    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <local:SignUpControl>

        </local:SignUpControl>
    </ScrollViewer>
</Grid>

MainWindow.xaml.cs没有代码...

SignUpControl.Xaml

<UserControl x:Class="WpfApp1.SignUpControl"
         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:local="clr-namespace:WpfApp1"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<StackPanel
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            TextBlock.TextAlignment="Center">

    <!--Login main content white box-->
    <Border Background="WhiteSmoke" 
                    Opacity="0.4"
                    CornerRadius="30"
                    Padding="15 50 15 15"
                    Width="350" 
                    Margin="50 50 50 0">

        <StackPanel>

            <!--Sign Up header-->
            <TextBlock FontSize="20" 
                           HorizontalAlignment="Center" 
                           VerticalAlignment="Top" 
                           Height="auto" 
                           FontFamily="Goudy Stout" >Sign Up</TextBlock>

            <!--Sign up subtext-->
            <TextBlock FontSize="14" 
                               HorizontalAlignment="Center" 
                               VerticalAlignment="Top"
                               Height="auto" 
                               FontFamily="Ravie" >It's about to get fun!</TextBlock>

            <!--Inner grid for Username & Password-->
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <!--Textbox for username-->
                <TextBox Grid.Row="0" BorderThickness="0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontFamily="Arial" FontWeight="Bold" FontSize="14" x:Name="UsernameBox" Margin="5"/>
                <TextBlock IsHitTestVisible="False" Text="Username" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10,0,0,0" FontFamily="Arial" FontWeight="Bold" FontSize="14" Foreground="Black">
                    <TextBlock.Style>
                        <Style TargetType="x:Type TextBlock">
                            <Setter Property="Visibility" Value="Collapsed"/>
                            <Style.Triggers>
                                <DataTrigger Binding="Binding Text, ElementName=UsernameBox" Value="">
                                    <Setter Property="Visibility" Value="Visible"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>

                <!--PasswordBox-->
                <TextBox Grid.Row="1" BorderThickness="0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontFamily="Arial" FontWeight="Bold" FontSize="14" x:Name="passwordBox" Margin="5"/>
                <TextBlock Grid.Row="1" IsHitTestVisible="False" Text="password" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="10,0,0,0" FontFamily="Arial" FontWeight="Bold" FontSize="14" Foreground="Black">
                    <TextBlock.Style>
                        <Style TargetType="x:Type TextBlock">
                            <Setter Property="Visibility" Value="Collapsed"/>
                            <Style.Triggers>
                                <DataTrigger Binding="Binding Text, ElementName=passwordBox" Value="">
                                    <Setter Property="Visibility" Value="Visible"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>

            </Grid>

            <!--Next Button-->
            <Button Content="Next" 
                            HorizontalAlignment="Center" 
                            FontWeight="Bold"
                            FontSize="14"
                            BorderThickness="0"
                            FontFamily="Goudy Stout"
                            Background="Transparent"
                            Padding="20 10"
                            Margin="0 10"
                            x:Name="NextButton"
                            Click="NextButton_Click"/>

        </StackPanel>

    </Border>

    <!--Border for PreRegistered account-->
    <Border Background="WhiteSmoke" 
                    Opacity="0.4"
                    CornerRadius="50"
                    Padding="0"
                    Width="400" 
                    Height="auto"
                    Margin="0 12.5 0 0">

        <!--Already registered button-->
        <Button Content="I already have an account"  
                    HorizontalAlignment="Center" 
                    Opacity="0.8"
                    FontSize="13"
                    BorderThickness="0" 
                    FontFamily="Goudy Stout" 
                    Background="Transparent"
                    Foreground="Black"
                    x:Name="alreadyRegBtn"
                    Padding="0 10"
                    Margin="0 5 0 5"/>

    </Border>

</StackPanel>

我该如何做这个解决方案,我可以在同一个窗口上的用户控件之间进行切换,当然,在感谢屏幕之后,我将使用相同的逻辑转到“登录!”等等……

【问题讨论】:

看看页面导航。 【参考方案1】:

当我不使用PrismDependency Injection 时,我通常使用视图模型优先方法。

在这种情况下,我们的 Windows ViewModel 上有一个属性,该属性是其他 UserControls ViewModel 继承自的类,通常只使用具有 INotifyPropertyChanged 隐含的 ViewModelBase 类:

private ViewModelBase currentViewModel;
public ViewModelBase CurrentViewModel

    get  return currentViewModel; 
    set  currentViewModel = value; NotifyPropertyChanged(); 

现在在你的MainWindow 里面,就像@Tomtom 说你有一个ContentControl 绑定到那个属性。这意味着使用 DataTemplates 您可以有不同的 View 显示,具体取决于该属性上当前的 ViewModel 类型。

<Window.Resources>
    <DataTemplate DataType="x:Type viewmodels:ViewModel1">
        <views:View1/>
    </DataTemplate>
    <DataTemplate DataType="x:Type viewmodels:ViewModel2">
        <views:View2/>
    </DataTemplate>
</Window.Resources>

<ContentControl Content="Binding CurrentViewModel"/>

有了这个,你需要做的就是有一些逻辑来改变 MainWindow ViewModel 上的 ViewModel 并且 View 将更新以显示该 ViewModel 的正确 View。

编辑:需要注意的一点是,人们使用许多不同的方式来实现你想要的东西,它们都没有真正的正确或错误,但它们都适合不同的人的需求和编码风格。

【讨论】:

我是否创建一个包含 ViewModelBase 部分的新类?不能完全弄清楚那部分..我对此很陌生。 你会的,本质上,使用MVVM 你最终会得到很多ViewModels 这些相当于后面的代码但没有直接关系,即直接访问控件, View 这种分离水平很好。通常ViewModels 会使用类似的代码位,最值得注意的是INotifyPropertyChanged 的实现。因此,我们可以将该代码移动到一个名为 ViewModelBase 的类中,并让我们所有其他的 ViewModels 继承它并使用该功能。这种多态性意味着每个 ViewModel 都有自己的类型和 ViewModel 基础类型。 这意味着我们可以在 Windows ViewModel 上拥有类型为ViewModelBase 的属性并将其切换到任何 ViewModel,因为它们在技术上属于该类型。 我无法理解它。我已经尝试使用你描述的方式,但我无法让它工作......我认为我也没有完全理解你在说什么。 我已经用一张图片更新了我的答案,但我不确定它是否会让它变得更加压倒性。【参考方案2】:

不久前我已经回答了一个类似的问题。

See this post

您可以在您的窗口中创建一个ContentControl,并在用户点击或其他地方切换绑定UserControl

【讨论】:

我已将主窗口 xaml 和 xaml.cs 更新为您在另一篇文章中提到的 (contentcontrol x:name="contentControl" & this.contentControl.content = "userControl.content") .虽然如果我现在想在完成第一个 userControl 后更改为另一个 usercontrol,我该如何继续? @user8478480 当然是因为我们不喜欢 *** 上的仅链接答案。这应该是一条评论,如果 OP 认为另一个问题与他们的相似,则该问题应作为重复关闭。它当然不值得赞成,您的赞成特权并不意味着补偿您认为不公平的反对票。请仅对好的帖子进行投票。 @Clemens 我明白你在说什么,也许他们没有完全正确地回答这个问题,评论会更好。但归根结底,他们已经继续帮助 OP,不应该因此而被否决。归根结底,他的答案没有错,因此将其向下推也无济于事,现在我们只有 2 个答案为 0。 @user8478480 没有错 并不完全正确,因为它仍然是仅链接的答案。我们只是不想拥有那个。参见例如在这里:meta.***.com/q/265552/1136211。这里当然有第二句话,但没有上下文就不是很有帮助。 @Clemens 我同意它不应该发布,我们不想看到它。就像一个注释,对于一个在 SO, OP 上不问太多问题的用户。有一个反对票的答案可能意味着对 OP “错误”,这也不是很好/有帮助

以上是关于如何在一个 xaml 页面中使用多个用户控件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义嵌套用户控件中引用另一个 XAML 元素?

wpf 带参数的用户控件,如何在xaml中引入

jQuery中一个页面中的多个用户控件

如何在两个项目共享的 xaml 文件中添加用户控件的引用

从其他 Xaml 文件绑定到用户控件中的元素

XAML 动画:如何使用 BLEND 为用户控件的外观和消失设置动画