0

I created the Login Entities (Login.cs) and also I created Logins property of type DbSet of Login to save logins with (SubBVDbContext.cs) as public DbSet<Login> Logins { get; set;}, then I seed entries into the Login table in the (Configuration.cs) in Migration Folder. After that, I created the (LoginPageViewModel.cs) which includes LoginWrapper that wraps up all entities, as well as the (NavigationView.xaml) that allows navigation from model to another. I have already created (MainViewModel.cs), and the MainWindow.xaml that contain the views of the models and the navigations between them. What I want is to display the LoginPage first then show the other views.

Login.cs

 public class Login
{
    public int Id { get; set; }

    [Required]
    [StringLength(50)]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

LoginDetailView.xaml(UserControl)

<StackPanel Orientation="Horizontal">
        <TextBox Text="{Binding Login.Email, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <PasswordBox PasswordChar="{Binding Login.Password, UpdateSourceTrigger=PropertyChanged}" />
 </StackPanel>
 <Button Width="100" ToolTip="Login to Subcontractors" HorizontalAlignment="Center" Content="login"/>

NavigationViewModel.xaml (UserControl)

  <UserControl.Resources>
    <Style x:Key="NaviItemContainerStyle" TargetType="ContentPresenter">
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="Margin" Value="2"/>
    </Style>
    <DataTemplate x:Key="NaviItemTemplate">
        <Button Content="{Binding DisplayMember}"
                Command="{Binding OpenDetailViewCommand}">
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="grid">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Cursor" Value="Hand"/>
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Trigger>
                        <Trigger Property="IsPressed" Value="True">
                            <Setter Property="Foreground" Value="DarkRed"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="300"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <GroupBox Header="Subcontarctors">
        <ScrollViewer VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Auto">
            <ItemsControl ItemsSource="{Binding Subs}"
                ItemContainerStyle="{StaticResource NaviItemContainerStyle}"
                ItemTemplate="{StaticResource NaviItemTemplate}"/>
        </ScrollViewer>
    </GroupBox>
    <GroupBox Header="POs" Grid.Row="1" >
        <ScrollViewer VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Auto" >
            <ItemsControl ItemsSource="{Binding SubPOs}"
                ItemContainerStyle="{StaticResource NaviItemContainerStyle}"
                ItemTemplate="{StaticResource NaviItemTemplate}"/>
        </ScrollViewer>
    </GroupBox>
</Grid>

LoginPageViewModel.cs

public class LoginPageViewModel:ViewModelBase
{
    private LoginWrapper _login;
    private IMessageDialogService _messageDialogService;

    public LoginPageViewModel(IMessageDialogService messageDialogService)
    {
        _messageDialogService = messageDialogService;
    }

    public LoginWrapper Login
    {
        get { return _login; }
        private set
        {
            _login = value;
            OnPropertyChanged();
        }
    }
}

LoginWrapper.cs

 public class LoginWrapper : ModelWrapper<Login>
{
    public LoginWrapper(Login model) : base(model)
    {
    }

    public int Id { get { return Model.Id; } }

    public string Email
    {
        get { return GetValue<string>(); }
        set { SetValue(value); }
    }

    public string Password
    {
        get { return GetValue<string>(); }
        set { SetValue(value); }
    }

}

App.xaml.cs

private void Application_Startup(object sender, StartupEventArgs e)
    {
        var bootstrapper = new Bootstrapper();
        var container = bootstrapper.Bootstrap();

        var mainWindow = container.Resolve<MainWindow>();
        mainWindow.Show();
    }

Note: in the Bootstrapper there is a container that contains the whole models and the views For Example:

  public class Bootstrapper
{
    public IContainer Bootstrap()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<EventAggregator>().As<IEventAggregator>().SingleInstance();

        builder.RegisterType<SubBVDbContext>().AsSelf();

        builder.RegisterType<MainWindow>().AsSelf();
        builder.RegisterType<SubPODetailViewModel>().As<ISubPODetailViewModel>();
        builder.RegisterType<LoginPageViewModel>.AsSelf();

MainWindow.xaml

<Window.Resources>
    <DataTemplate DataType="{x:Type viewModel:SubDetailViewModel}">
        <view:SubDetailView/>
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type viewModel:SubPODetailViewModel}">
        <view:SubPODetailView/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type viewModel:LoginPageViewModel}">
        <view:LoginDetailView/>
    </DataTemplate>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Menu Grid.ColumnSpan="2" FontSize="13">
        <MenuItem Header="Create">
            <MenuItem Header="New Subcontractor" Command="{Binding CreateNewDetailCommand}"
                  CommandParameter="{x:Type viewModel:SubDetailViewModel}"/>
            
            <MenuItem Header="New P.O." Command="{Binding CreateNewDetailCommand}"
                  CommandParameter="{x:Type viewModel:SubPODetailViewModel}"/>
        </MenuItem>
    </Menu>
    
    <view:NavigationView Grid.Row="1" DataContext="{Binding NavigationViewModel}"/>
    <ContentControl Grid.Row="1" Grid.Column="1" Content="{Binding DetailViewModel}"/>
</Grid>

The Model view 1,The Model view 2

The SolutionExplorer Folders

The Link for My WPF App: http://www.filefactory.com/file/4of3jrkspmog/SubBvApp.zip

Maya
  • 59
  • 6
  • What is the code of the MainViewModel? It seems you want to set the DetailViewModel to be the LoginViewModel as the starting point. But I would need to see your MainViewModel code to check. – Daniel Marques Nov 18 '20 at 13:10
  • I have added mainviewmodel with what is included in solution explorer. Thanks. – Maya Nov 18 '20 at 13:35
  • You simply have to initialize your view source with the `LoginViewModel` so that the proper `DataTemplate` can apply. It's not clear where this view should be displayed. I assume the `NavigationView` is supposed to display the view? – BionicCode Nov 18 '20 at 14:26
  • Don't you just have to set _detailViewModel to an instance of LoginViewModel? Imo a singleton navigationservice should come from your container to set detailviewmodel somehow. It can then be injected into your navigation control. And i would lose that login completed event. – Andy Nov 18 '20 at 17:22
  • I added the NavigationViewModel code above, but shall I create a Repository also for the User class that contain an email for user and password. – Maya Nov 19 '20 at 04:32
  • @BionicCode can you show me how to implement the login page, please? Thanks – Maya Nov 22 '20 at 05:20
  • Sure, but I need more details. You said `MainWindow` is where the `LoginView` should be displayed. But it's not clear which control is hosting your views i.e. *where exactly* the page should be displayed. That's why I asked in my last comment to provide more details like is it `NavigationView` or what is the hosting control for the page views? Did you wrote the code yourself? Then you should know about the mechanism how to load views. Please provide the required details. – BionicCode Nov 22 '20 at 10:00
  • Everything looks hardwired. Do you want to show it in the `ContentPresenter` which is wired to `DeatilsViewModel`? Does [this example](https://stackoverflow.com/a/61323201/3141792) helps to guide you to implement simple dynamic view switching? – BionicCode Nov 22 '20 at 10:08
  • @BionicCode I updated the details above, and I hope it's understable now and Yes, i want to be shown in the ContentPresenter. But my problem how to implement that and the LoginPageViewModel, Thanks. – Maya Nov 26 '20 at 13:59
  • You have to redesign your application (slightly) to allow dynamic view navigation. The link in my last comment shows a simple example. You should follow the steps. It does exactly what you want. – BionicCode Nov 26 '20 at 14:04
  • You are missing a lot of key details like how you load your page views. But it looks like you have to assign the login view model to the `DetailViewModel` property (don't see where it is defined - missing detail). You should follow the example link and basically copy the navigation logic. The `DetailViewModel` property should be renamed to `SelectedPage`. It's all in the example. – BionicCode Nov 26 '20 at 14:19
  • @BionicCode I uploaded the zip file above for my whole App, just click (slow download) then, click (start download), then you will be able to see my whole files. – Maya Nov 27 '20 at 11:57
  • after clicking (slow download), click continue download that appears at bottom then click start download – Maya Nov 27 '20 at 12:06

0 Answers0