简体   繁体   English

在 mvvm 应用程序中导航后,子 ViewModel 中的命令不起作用

[英]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.我在桌面上工作 wpf MVVM 应用程序包含一个 MainWindow,其中包含为不同的 UserControls 进行导航的内容控件。 commands of the MainViewModel in the MainWindow working well. MainWindow 中 MainViewModel 的命令运行良好。 but commands of the navigated ViewModels not working.但导航 ViewModel 的命令不起作用。 the code of the app.cs: navigationStore is the store for the navigated viewModels app.cs 的代码:navigationStore 是导航 viewModel 的商店

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 MainVM NavigateUsersCommand 的代码运行良好并为 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 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导航 ViewModel 的代码,它的名称 UsersVM

the NavigateUsersSelectCommand navigate to new View and NavigateMainBackGroundCommand navigate back to MainBackGroundView both commands not working NavigateUsersSelectCommand 导航到新视图和 NavigateMainBackGroundCommand 导航回 MainBackGroundView 两个命令都不起作用

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用户查看的 xaml 代码

<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 mainBackGroundView 的 xaml 代码

<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 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 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这是我在 GitHub github.com/amryakout1990/Yakout.git 上的代码,我想解决我的问题

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.这需要一个 UserSelectVM 类型的命令参数。

You are not passing that because you define no commandparameter in xaml.你没有通过它,因为你在 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.我还以为你的 xaml 错误 window in vs2022 或 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.我想这是您想要的选定用户,因此您可以创建命令参数 selecteditem 或者您可以绑定 selecteditem 并在您那里的匿名方法中引用它。

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.我建议你先解决那个问题,看看你是否重复出现类似的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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