简体   繁体   中英

commands in the child ViewModel not working after navigation in mvvm app

iam working on desktop wpf MVVM app contain one MainWindow containing content control that make navigation for diffrent UserControls. commands of the MainViewModel in the MainWindow working well. but commands of the navigated ViewModels not working. the code of the app.cs: navigationStore is the store for the navigated viewModels

public partial class App : Application
{

    protected override void OnStartup(StartupEventArgs e)
    {
        NavigationStore navigationStore = new NavigationStore();

        navigationStore.CurrentViewModel = new MainBackGroundVM();

        MainWindow = new MainWindow()
        {
            ///inistiation of the main with passing the CurrentViewModel to the mainVM
            DataContext = new MainVM(navigationStore)
        };
         MainWindow.Show();
        base.OnStartup(e);
    }
}

the code of MainVM NavigateUsersCommand working well and navigate for usersVM

class MainVM :Utilities.ViewModelBase
{


    private readonly NavigationStore _navigationStore;

    public ViewModelBase CurrentViewModel => _navigationStore.CurrentViewModel;

    public ICommand NavigateUsersCommand { get; }

    public MainVM(NavigationStore navigationStore)
    {
        _navigationStore = navigationStore;

        _navigationStore.CurrentViewModelChanged += _navigationStore_CurrentViewModelChanged;
        
        NavigateUsersCommand = new NavigateUsersCommand(navigationStore);            

 }

    private void _navigationStore_CurrentViewModelChanged()
    {
        OnPropertyChanged(nameof(CurrentViewModel));
    }
}

the code for MainWindow.xml

<Window x:Class="Yakout.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:fa="http://schemas.fontawesome.io/icons/"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:Yakout.ViewModels"
    xmlns:v="clr-namespace:Yakout.Views"
    xmlns:local="clr-namespace:Yakout"
    mc:Ignorable="d"
    Title="MainWindow" Height="700" Width="1100" Background="Transparent" AllowsTransparency="True" WindowStartupLocation="CenterScreen" WindowStyle="None" ResizeMode="NoResize" >
<Window.DataContext>
    <vm:NavigationVM></vm:NavigationVM>
</Window.DataContext>
<Border  BorderThickness="2" BorderBrush="BlueViolet" Background="White">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="5*"/>
        </Grid.RowDefinitions>
        <Button Style="{StaticResource btnCircle}" Grid.Column="1" Click="Button_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="Close" Grid.Column="1" Style="{StaticResource close}"/>
            </StackPanel >
        </Button>
        <Border Grid.Row="1" Background="BlueViolet" >
            <StackPanel >
                <Button Style="{StaticResource btnMainMenu}" Name="btnPOS" 
                        Command="{Binding NavigatePosCommand}">
                    <StackPanel Style="{StaticResource stack}" Orientation="Horizontal">
                        <fa:ImageAwesome Icon="ShoppingCart" Style="{StaticResource faMainMenu}" Margin="40 0 0 0"/>
                        <TextBlock Text="Point Of Sale" Style="{StaticResource tbMainMenu}" Margin="30 10 0 0"/>
                    </StackPanel>
                </Button>
                <Button Style="{StaticResource btnMainMenu}" Name="btnSetUp" Command="{Binding NavigateUsersCommand}">
                    <StackPanel Style="{StaticResource stack}" Orientation="Horizontal" >
                        <fa:ImageAwesome Icon="Key" Style="{StaticResource faMainMenu}"/>
                        <TextBlock Text="Set Up" Style="{StaticResource tbMainMenu}"/>
                    </StackPanel>
                </Button>

                <Button Style="{StaticResource btnMainMenu}" Name="btnReports" 
                        Command="{Binding NavigateUsersSelectCommand}">
                    <StackPanel Style="{StaticResource stack}" Orientation="Horizontal">
                        <fa:ImageAwesome Icon="PencilSquare" Style="{StaticResource faMainMenu}"/>
                        <TextBlock Text="Reports" Style="{StaticResource tbMainMenu}"/>
                    </StackPanel>
                </Button>
                <Button Style="{StaticResource btnMainMenu}" Name="btnOptions"
                        Command="{Binding NavigateMainBackGroundCommand}" >
                    <StackPanel Style="{StaticResource stack}" Orientation="Horizontal">
                        <fa:ImageAwesome Icon="HandPaperOutline" Style="{StaticResource faMainMenu}"/>
                        <TextBlock Text="Options" Style="{StaticResource tbMainMenu}"/>
                    </StackPanel>
                </Button>
                <Button Name="btnLogOut" Style="{StaticResource btnMainMenu}" Margin="5 212 5 0" Click="btnLogOut_Click">
                    <StackPanel Style="{StaticResource stack}" Orientation="Horizontal">
                        <fa:ImageAwesome Icon="CircleOutlineNotch" Style="{StaticResource faMainMenu}"/>
                        <TextBlock Text="Log Out" Style="{StaticResource tbMainMenu}"/>
                    </StackPanel>
                </Button>
            </StackPanel>
        </Border>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image Source="/image/R.png"/>
            <StackPanel Orientation="Vertical" Grid.Column="1">
                <TextBlock Text="Yakout POS" Margin="5 10 5 5" FontSize="25" FontWeight="Bold" HorizontalAlignment="Center"/>
                <TextBlock Text="1.0.0.1" FontSize="15" FontWeight="Bold" HorizontalAlignment="Center"/>
                <TextBlock Text="Yakout Company" FontSize="15" Foreground="DodgerBlue" FontWeight="Bold" HorizontalAlignment="Center" TextDecorations="Underline"/>
            </StackPanel>
        </Grid>
        <Border Grid.Column="1" Background="BlueViolet">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="auto"/>
                </Grid.ColumnDefinitions>
                <Canvas>
                    <Label x:Name="lbl" FontSize="15" Foreground="White" Canvas.Top="10" Canvas.Right="20" Content="{Binding MyTimer}"/>
                    <TextBlock Text="Point Of Sale" Canvas.Left="250" FontSize="30" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0 25 0 0"/>
                    <Ellipse Width="40" Height="40" Fill="DarkViolet" Canvas.Left="150" Canvas.Top="20" StrokeThickness="10"/>
                    <Ellipse Width="40" Height="40" Fill="DarkViolet" Canvas.Right="230" Canvas.Top="20" StrokeThickness="10"/>
                </Canvas>
            </Grid>
        </Border>
        <Rectangle Stroke="BlueViolet" StrokeThickness="3" Grid.Column="0" Grid.Row="0"/>
        <ContentControl Content="{Binding CurrentViewModel}" Grid.Row="1" Grid.Column="1" >
        </ContentControl>
        <!--CurrentView-->
    </Grid>
</Border>

the code of the navigated ViewModel, its name UsersVM

the NavigateUsersSelectCommand navigate to new View and NavigateMainBackGroundCommand navigate back to MainBackGroundView both commands not working

class UsersVM : Utilities.ViewModelBase
{
    public ICommand NavigateUsersSelectCommand { get; }

    public ICommand NavigateMainBackGroundCommand { get; }

    public UsersVM(NavigationStore navigationStore,SelectedUserStore selectedUserStore)
    {
        _navigationStore = navigationStore;
      
        NavigateMainBackGroundCommand = new NavigateCommand<MainBackGroundVM>(new NavigationService<MainBackGroundVM>(navigationStore, () => new MainBackGroundVM()));

        NavigateUsersSelectCommand = new NavigateCommand<UserSelectVM>(new NavigationService<UserSelectVM>(navigationStore, () => new UserSelectVM(_navigationStore)));

    }


}

the xaml code for the usersView

<UserControl x:Class="Yakout.Views.Users"
         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:fa="http://schemas.fontawesome.io/icons/"
         xmlns:local="clr-namespace:Yakout.Views"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800" Style="{StaticResource user}"
         >
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <!--Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.NavigateUsersSelectCommand}">-->

    <StackPanel Orientation="Horizontal">
        <Button x:Name="select" Style="{StaticResource btnUsers}"
                Command="{Binding NavigateUsersSelectCommand}">
            <StackPanel>
                <fa:ImageAwesome Icon="HandPointerOutline"  Style="{StaticResource fa}"/>
                <TextBlock Text="Select" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="new" Style="{StaticResource btnUsers}" Click="new_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="NewspaperOutline"  Style="{StaticResource fa}"/>
                <TextBlock Text="New" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="save" Style="{StaticResource btnUsers}" Click="save_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="Save"  Style="{StaticResource fa}"/>
                <TextBlock Text="Save" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="first" Style="{StaticResource btnUsers}" Click="first_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="FastBackward"  Style="{StaticResource fa}"/>
                <TextBlock Text="First" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="back" Style="{StaticResource btnUsers}" Click="back_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="Backward"  Style="{StaticResource fa}"/>
                <TextBlock Text="Back" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="next" Style="{StaticResource btnUsers}" Click="next_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="Forward"  Style="{StaticResource fa}"/>
                <TextBlock Text="Next" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>
        <Button x:Name="last" Style="{StaticResource btnUsers}" Click="last_Click">
            <StackPanel>
                <fa:ImageAwesome Icon="FastForward"  Style="{StaticResource fa}"/>
                <TextBlock Text="Last" Style="{StaticResource btnText}"/>
            </StackPanel>
        </Button>

    </StackPanel>
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <StackPanel>
            <Label Content="User Name" Style="{StaticResource  labelUsers}"/>
            <Label Content="Password" Style="{StaticResource  labelUsers}"/>
            <Label Content="Full Name" Style="{StaticResource  labelUsers}"/>
            <Label Content="Job Des" Style="{StaticResource  labelUsers}"/>
            <Label Content="Email" Style="{StaticResource  labelUsers}"/>
            <Label Content="Phone" Style="{StaticResource  labelUsers}"/>

        </StackPanel>
        <StackPanel Grid.Column="1">
            <TextBox Name="tx1" Style="{StaticResource box}" Text="{Binding Path=UserName,Mode=OneWay}"/>
            <TextBox Name="tx2" Style="{StaticResource box}" Text="{Binding Path=Password,Mode=OneWay}"/>
            <TextBox Name="tx3" Style="{StaticResource box}" Text="{Binding Path=FullName,Mode=OneWay }"/>
            <TextBox Name="tx4" Style="{StaticResource box}" Text="{Binding Path=JobDes,Mode=OneWay}"/>
            <TextBox Name="tx5" Style="{StaticResource box}" Text="{Binding Path=Email,Mode=OneWay }"/>
            <TextBox Name="tx6" Style="{StaticResource box}" Text="{Binding Path=Phone,Mode=OneWay }"/>
        </StackPanel>
        <Canvas Grid.Column="2">
            <Button  x:Name="btnBack" Style="{StaticResource btnPages}"
                     Canvas.Right="5" Canvas.Bottom="5"
                     Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.NavigateMainBackGroundCommand}">
                <StackPanel>
                    <fa:ImageAwesome Icon="Backward" Style="{StaticResource faPagesBack}"/>
                    <TextBlock Text="Back" Style="{StaticResource tbPagesBack}"/>
                </StackPanel>
            </Button>
        </Canvas>
    </Grid>
</Grid>

the xaml code for the mainBackGroundView

<UserControl x:Class="Yakout.Views.MainBackGround"
         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:Yakout.Views"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <Image Source="/image/kkk.jpg" Stretch="Fill"/>
</Grid>

data template for the app

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:vm="clr-namespace:Yakout.ViewModels"
                xmlns:view="clr-namespace:Yakout.Views">



<DataTemplate DataType="{x:Type vm:OptionsVM}">
    <view:Options/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:MainBackGroundVM}">
    <view:MainBackGround/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:SetUpVM}">
    <view:SetUP/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:PosVM}">
    <view:Pos/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:ReportsVM}">
    <view:Reports/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:UsersVM}">
    <view:Users/>
</DataTemplate>

<DataTemplate DataType="{x:Type vm:UserSelectVM}">
    <view:UserSelect/>
</DataTemplate>

code for the app.xml

<Application x:Class="Yakout.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:Yakout"
         >

<Application.Resources>

        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/StylesMainWindow.xaml" />
                <ResourceDictionary Source="Styles/StylesMain.xaml" />
                <ResourceDictionary Source="Styles/StylesUcOptions.xaml" />
                <ResourceDictionary Source="/Utilities/DataTemplate.xaml"/>
                <ResourceDictionary Source="/Styles/StylesUsers.xaml"/>
                <ResourceDictionary Source="/Styles/StylesUserSelect.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>


</Application.Resources>

NavigationService

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yakout.Stores;

namespace Yakout.Utilities
{
    class NavigationService<TViewModel> 
        where TViewModel:ViewModelBase
    {
        private readonly NavigationStore _navigationStore;

        private readonly Func<TViewModel> _CreateViewModel;

        public NavigationService(NavigationStore navigationStore,Func<TViewModel>CreateViewModel)
        {
            _navigationStore = navigationStore;
            _CreateViewModel = CreateViewModel;
        }
        public void Navigate()
        {
            _navigationStore.CurrentViewModel = _CreateViewModel();
        }
    }
}

ParameterNavigationService

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yakout.Stores;

namespace Yakout.Utilities
{
    class ParameterNavigationService<TParameter, TViewModel>
        where TViewModel:ViewModelBase
    {
        private readonly NavigationStore _navigationStore;
        private readonly Func<TParameter,TViewModel> _createVM;

        public ParameterNavigationService(NavigationStore navigationStore, Func<TParameter, TViewModel> createVM)
        {
            _navigationStore = navigationStore;
            _createVM= createVM;

        }

        public void Navigate(TParameter parameter)
        {
            _navigationStore.CurrentViewModel = _createVM(parameter);
        }
    }
}

NavigateMainBackGroundCommand

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Navigation;
using Yakout.Stores;
using Yakout.Utilities;
using Yakout.ViewModels;

namespace Yakout.Commands
{
    class NavigateMainBackGroundCommand : Utilities.CommandBase
    {
        /// <summary>
        /// حاليا مفيش احتياج لاوامر دي 
        /// </summary>

        private readonly NavigationService<MainBackGroundVM> _navigationService;

        private readonly MainBackGroundVM _mainBackGroundVM;

        public NavigateMainBackGroundCommand(MainBackGroundVM mainBackGroundVM,  NavigationService<MainBackGroundVM>  navigationService)
        {
            _navigationService = navigationService;
            _mainBackGroundVM = mainBackGroundVM;
        }

        public override void Execute(object parameter)
        {
            _navigationService.Navigate();
        }
    }
}

NavigateUsersCommand

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Yakout.Stores;
using Yakout.ViewModels;

namespace Yakout.Commands
{
    class NavigateUsersCommand : Utilities.CommandBase
    {
        private readonly NavigationStore _navigationStore;

        private readonly SelectedUserStore _selectedUserStore;

        public NavigateUsersCommand(NavigationStore navigationStore, SelectedUserStore selectedUserStore)
        {
            _navigationStore = navigationStore;
            _selectedUserStore = selectedUserStore;
        }

        public override void Execute(object parameter)
        {
            _navigationStore.CurrentViewModel = new UsersVM(_navigationStore,_selectedUserStore);
        }
    }
}

this is my code on GitHub github.com/amryakout1990/Yakout.git i want solution for my problem

Looking at one of these commands you have in your view:

    <Button x:Name="select" Style="{StaticResource btnUsers}"
            Command="{Binding NavigateUsersSelectCommand}">

In the viewmodel:

  NavigateUsersSelectCommand = new NavigateCommand<UserSelectVM>(new NavigationService<UserSelectVM>(navigationStore, () => new UserSelectVM(_navigationStore)));

That expects a command parameter of UserSelectVM type.

You are not passing that because you define no commandparameter in xaml.

Does it even bind? I would have thought there'd be an error in your xaml errors window in vs2022 or the output window.

I guess this is the selected user you want so you could make the commandparameter selecteditem or you could bind selecteditem and reference it in the aonymous method you have there.

But that is why that command does not work.

I didn't look at other commands because there's quite a lot of code to look through. I suggest you fix that one first and see if you have a similar issue repeated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM