Prism 6 Navigation Wierdness

本文关键字:Wierdness Navigation Prism | 更新日期: 2023-09-27 18:28:11

我仍在学习棱镜,我想了解导航。在阅读了手册并关注了@brianlagunas MVVM在线制作的简单网络研讨会后,我决定尝试一个小项目,看看。当我试图导航到一个视图时,我会遇到一个stackerflow异常,该视图的视图模型数据绑定到我的视图上的一些控件。下面是代码:

带有空视图的纵断面图模型:

<UserControl x:Class="SampleLogin.Views.Profile"
         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:prism="http://prismlibrary.com/"
         prism:ViewModelLocator.AutoWireViewModel="True"
         xmlns:local="clr-namespace:SampleLogin.Views"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <TextBlock x:Name="ProfileTextBlock" HorizontalAlignment="Center" Margin="74,29,78,0" TextWrapping="Wrap" Text="PROFILE PAGE" VerticalAlignment="Top" Height="45" Width="148" FontSize="21.333" FontWeight="Bold"/>
    <TextBlock x:Name="Username" HorizontalAlignment="Left" Height="26" Margin="103,96,0,0" TextWrapping="Wrap" Text="{Binding username}" VerticalAlignment="Top" Width="130"/>
    <TextBlock x:Name="LoginTime" HorizontalAlignment="Left" Margin="109,152,0,0" TextWrapping="Wrap" Text="{Binding LoginTime}" VerticalAlignment="Top" Width="124" Height="33"/>
    <Label x:Name="label" Content="Username :" HorizontalAlignment="Left" Margin="10,96,0,0" VerticalAlignment="Top" Width="71" FontWeight="Bold"/>
    <Label x:Name="label1" Content="Login-Time:" HorizontalAlignment="Left" Height="26" Margin="12,159,0,0" VerticalAlignment="Top" Width="86" FontWeight="Bold"/>
</Grid>

但它有一个空的视图模型,并且加载良好。

这是另一个视图,它有一个简单的表单,数据绑定到它的视图模型

<UserControl x:Class="SampleLogin.Views.LoginUser"
         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:prism="http://prismlibrary.com/"
         prism:ViewModelLocator.AutoWireViewModel="True"
         xmlns:local="clr-namespace:SampleLogin.Views"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="325">
<Grid>
    <Label x:Name="usernameLabel" Content="Username :" HorizontalAlignment="Left" Margin="10,93,0,0" VerticalAlignment="Top" Width="113" Height="35" FontSize="18.667" FontWeight="Bold"/>
    <Label x:Name="label" Content="Password :&#xD;&#xA;" HorizontalAlignment="Left" Margin="10,146,0,0" VerticalAlignment="Top" Width="100" Height="38" FontSize="18.667" FontWeight="Bold"/>
    <TextBox x:Name="Username" HorizontalAlignment="Left" Height="35" Margin="132,93,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="178" Text="{Binding Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <PasswordBox x:Name="passwordBox" HorizontalAlignment="Left" Margin="132,146,0,0" VerticalAlignment="Top" Width="178" Height="35"/>
    <Button x:Name="Loginbtn" Content="Login" HorizontalAlignment="Left" Margin="85,208,0,0" VerticalAlignment="Top" Width="89" Height="42" FontSize="18.667" FontWeight="Bold"
            Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=passwordBox}" />
    <Button x:Name="Logoutbtn" Content="Logout" HorizontalAlignment="Left" Margin="230,208,0,0" VerticalAlignment="Top" Width="80" Height="42" FontWeight="Bold" FontSize="18.667"/>
</Grid>

以下是视图模型的绑定:让它非常简单,只是为了理解概念:

 public class LoginUserViewModel : BindableBase
{
    private AuthenticationService _auth;
    public DelegateCommand<object> LoginCommand { get; set; }
    public LoginUserViewModel(AuthenticationService auth)
    {
        _auth = auth;
        LoginCommand = new DelegateCommand<object>(LoginUser, CanLoginUser);
    }
    private void LoginUser(object obj)
    {
        var passwdbox = obj as PasswordBox;
        _auth.LoginUser(Username, passwdbox.SecurePassword);
    }
    private bool CanLoginUser(object obj)
    {
        var password = obj as PasswordBox;
        return string.IsNullOrWhiteSpace(Username);
    }
    private string _username = "Enter Username here";
    public string Username
    {
        get { return _username; }
        set { SetProperty(ref _username, value); }
    }
}

这里是MainWindowView模型,它使用我的主窗口视图顶部的按钮来处理导航。

    public class MainWindowViewModel : BindableBase
{
    IRegionManager _regions;
    public DelegateCommand<string> NavigationCommand { get; set; }
    public MainWindowViewModel(IRegionManager regions)
    {
        _regions = regions;
        NavigationCommand = new DelegateCommand<string>(Navigate);
    }
    private void Navigate(string uri)
    {
        _regions.RequestNavigate("ContentRegion", uri);
    }
}

最后,这里是绑定到视图模型的MainWindowViewModel:

<Window x:Class="SampleLogin.Views.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:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True"
    xmlns:local="clr-namespace:SampleLogin.Views"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
        <Button Content="Login" Margin="5" Command="{Binding NavigationCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" CommandParameter="LoginUser" />
        <Button Content="Home" Margin="5" Command="{Binding NavigationCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" CommandParameter="Home"/>
        <Button Content="Profile" Margin="5" Command="{Binding NavigationCommand}" CommandParameter="Profile"/>
    </StackPanel>
    <ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
</Grid>

我觉得这很奇怪。只要ViewModel为空,当我单击屏幕顶部的按钮进行导航时,第一个视图就会工作。与具有表单的视图相同,如果我注释掉ViewModel,它将毫无问题地导航,显示表单和所有内容。但是如果数据绑定在视图模型中,我会得到异常。有什么想法吗?!我被践踏了,不确定我的错误在哪里。

编辑:

考虑过这个问题并尝试将其向前推进后,我发现错误来自于我的LoginUserViewModel具有构造函数参数这一事实,这就是我出现错误的原因,我尝试在引导程序寄存器LoginUserView模型的依赖项中使用统一容器,但我仍然会收到错误,有人知道吗?

Prism 6 Navigation Wierdness

经过更多的搜索和提问,我得到了这个问题的答案。我和很棒的@brianLagunas进行了交谈,并与他分享了我的代码,他理解了我的问题。它在一个领域模型中,我没有在我的帖子中包括它。

public class User : IUser
{
    public User()
    {
    }
    public User(User user){} //this is the problem line
    [Required]
    [Key]
    public int UserId { get; set; }
    [Required(ErrorMessage ="You must supply a Username")]
    [DataType(DataType.Text)]
    public string Username { get; private set; }
    [Required(ErrorMessage = "You must enter a valid password to Login!")]
    public SecureString Password { get; private set; }
    [DataType(DataType.Time)]
    [Required]
    public TimeSpan TimeLoggedIn { get; private set; }
    [DataType(DataType.Date)]
    public DateTime LoginHistory { get; private set; }
    public void SetUserDetails(string username, TimeSpan date, DateTime History)
    {
        if(string.IsNullOrWhiteSpace(username))
        {
            throw new ArgumentNullException("You cannot have any of the Login Fields empty..!");
        }
        Username = username;
        TimeLoggedIn = date;
        LoginHistory = History;
    }
}

第二个构造函数是一个无限循环,这就是我得到的堆栈溢出错误。删除该构造函数解决了问题,一切都很好。