实现导航的前进和后退Button的IsEnable控制【WPF】

发布时间 2024-01-03 17:05:08作者: 閖

以一种很鬼畜的方式实现导航的前进和后退的按钮IsEnable控制,虽然含傻逼,但是也算是一个复习,所以记录下来。

为什么要这样

因为使用的是Prism实现的,开始时想要根据 CanGoBack和CanGoForward 去设置前进和后退两个按钮的状态。
如何发现,IRegionNavigationJournal 内部的CanGoBack和CanGoForward是没办法进行通知属性更新的,悲~。
如何想起了学习到了静态代理模式【本次复习的就是这】

代理 IRegionNavigationJournal

  • 在调用GoBack()和GoForward()时,进行通知更新
using CommunityToolkit.Mvvm.ComponentModel;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommunitySecurity.App.Commons
{
	public partial class NavigationJournalProfix : ObservableObject, IRegionNavigationJournal
	{
		private IRegionNavigationJournal Journal { get; set; }

		public bool CanGoBack => Journal.CanGoBack;

		public bool CanGoForward => Journal.CanGoForward;

		public IRegionNavigationJournalEntry CurrentEntry => Journal.CurrentEntry;

		public INavigateAsync NavigationTarget { get => Journal.NavigationTarget; set => Journal.NavigationTarget = value; }

		public NavigationJournalProfix(IRegionNavigationJournal Journal)
		{
			this.Journal = Journal;
		}

		public void GoBack()
		{
			Journal.GoBack();
			OnPropertyChanged(nameof(CanGoBack));
			OnPropertyChanged(nameof(CanGoForward));
		}

		public void GoForward()
		{
			Journal.GoForward();
			OnPropertyChanged(nameof(CanGoBack));
			OnPropertyChanged(nameof(CanGoForward));
		}

		public void RecordNavigation(IRegionNavigationJournalEntry entry, bool persistInHistory)
		{
			Journal.RecordNavigation(entry, persistInHistory);
		}

		public void Clear()
		{
			Journal.Clear();
		}
	}
}

ViewModel


using CommunitySecurity.App.Commons;
using CommunitySecurity.App.Commons.Models;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace CommunitySecurity.App.ViewModels
{
	public partial class MainWindowViewModel : ObservableObject
	{
		#region 属性

		/// <summary>
		/// 获取当前窗口
		/// </summary>
		private Window CuurentWindow

		{ get { return Application.Current.MainWindow; } }

		[ObservableProperty]
		private ObservableCollection<MenuBar> menuBarList;

		[ObservableProperty]
		private MenuBar settingMenuBar;

		[ObservableProperty]
		private MenuBar exitMenuBar;

		[ObservableProperty]
		[NotifyCanExecuteChangedFor(nameof(NavigateLoggingCommand))]
		private NavigationJournalProfix navigationJournal;

		private readonly IRegionManager regionManager;

		#endregion 属性

		#region Command

		/// <summary>
		/// ListBox 导航命令
		/// </summary>
		/// <param name="menuBar"></param>
		[RelayCommand]
		private void Navigate(MenuBar menuBar)
		{
			if (menuBar == null || string.IsNullOrWhiteSpace(menuBar.NameSpace)) return;
			NavigationParameters pairs = new NavigationParameters();
			regionManager.Regions["MainContentRegion"].RequestNavigate(menuBar.NameSpace, result =>
			{
				//成功了,就记录日志
				if ((bool)result.Result)
				{
					NavigationJournal = new NavigationJournalProfix(result.Context.NavigationService.Journal);
				}
			}, pairs);
		}

		/// <summary>
		/// 导航日志
		/// 返回上一步导航,前往下一步导航
		/// </summary>
		[RelayCommand(CanExecute = nameof(CanExecuteGoBackAndCanGoForward))]
		private void NavigateLogging(string obj)
		{
			if (obj.Equals("Left"))
			{
				//上一步
				NavigationJournal.GoBack();
			}
			else
			{
				//下一步
				NavigationJournal.GoForward();
			}
			NavigationJournal = new NavigationJournalProfix(NavigationJournal);
		}

		private bool CanExecuteGoBackAndCanGoForward(string obj)
		{
			if (NavigationJournal == null || string.IsNullOrWhiteSpace(obj) || (!"Left".Equals(obj) && !"Right".Equals(obj))) return false;

			return "Left".Equals(obj) ? NavigationJournal.CanGoBack : NavigationJournal.CanGoForward;
		}

		#endregion Command

		public MainWindowViewModel(IRegionManager regionManager)
		{
			DataInit();
			this.regionManager = regionManager;
		}

		#region 初始化

		/// <summary>
		/// 数据初始化准备
		/// </summary>
		private void DataInit()
		{
			//创建左侧菜单
			CreateLeftMenuBar();
		}

		/// <summary>
		/// 创建左侧菜单
		/// </summary>
		private void CreateLeftMenuBar()
		{
			settingMenuBar = new MenuBar("CogOutline", "设置", "SettingView");
			exitMenuBar = new MenuBar("LocationExit", "退出", "");

			menuBarList = new ObservableCollection<MenuBar>();
			menuBarList.Add(new MenuBar("MonitorEye", "环境监测", "SensorView"));
			menuBarList.Add(new MenuBar("VectorLink", "设备控制", "ActuatorView"));
			menuBarList.Add(new MenuBar("Security", "安防监控", "SecurityView"));
			menuBarList.Add(new MenuBar("Webcam", "视频监控", "MonitorView"));
			menuBarList.Add(new MenuBar("Tune", "配置", "ConfigOptionView"));
		}

		#endregion 初始化
	}
}

View

<Window
    x:Class="CommunitySecurity.App.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:prism="http://prismlibrary.com/"
    Width="1200"
    Height="650"
    MaxHeight="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}}"
    AllowsTransparency="True"
    Background="Transparent"
    FontFamily="{materialDesign:MaterialDesignFont}"
    TextElement.FontSize="14"
    TextElement.FontWeight="Medium"
    TextElement.Foreground="{DynamicResource MaterialDesignBody}"
    WindowStyle="None">
    <Border>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="70" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <!--  左侧导航栏  -->
            <materialDesign:Card
                Grid.Column="0"
                Padding="0,10,0,10"
                HorizontalContentAlignment="Center"
                Background="{DynamicResource PrimaryHueLightBrush}"
                Foreground="{DynamicResource PrimaryHueDarkForegroundBrush}"
                UniformCornerRadius="15">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="auto" />
                    </Grid.RowDefinitions>
                    <Button
                        Grid.Row="0"
                        Margin="0,0,0,30"
                        Background="{DynamicResource MaterialDesignTextFieldBoxBackground}"
                        Command="{Binding NavigateCommand}"
                        CommandParameter="{Binding SettingMenuBar}"
                        Style="{StaticResource MaterialDesignIconButton}"
                        ToolTip="MaterialDesignIconButton">
                        <materialDesign:PackIcon Foreground="White" Kind="{Binding SettingMenuBar.Icon}" />
                    </Button>



                    <ListBox
                        Grid.Row="1"
                        Width="70"
                        VerticalAlignment="Center"
                        HorizontalContentAlignment="Center"
                        VerticalContentAlignment="Center"
                        materialDesign:HintAssist.Hint="Search"
                        ItemContainerStyle="{DynamicResource MyListBoxItemStyle}"
                        ItemsSource="{Binding MenuBarList}">

                        <!--  触发器  -->
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="SelectionChanged">
                                <i:InvokeCommandAction Command="{Binding NavigateCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}" />
                            </i:EventTrigger>
                        </i:Interaction.Triggers>

                        <!--  模板  -->
                        <ListBox.ItemTemplate>
                            <DataTemplate>

                                <Button
                                    Width="40"
                                    Height="40"
                                    Margin="0,5"
                                    DockPanel.Dock="Top"
                                    Focusable="False"
                                    IsHitTestVisible="False"
                                    Style="{StaticResource MaterialDesignIconButton}"
                                    ToolTip="MaterialDesignIconButton">
                                    <materialDesign:PackIcon Foreground="White" Kind="{Binding Icon}" />
                                </Button>
                            </DataTemplate>
                        </ListBox.ItemTemplate>

                    </ListBox>

                    <Button
                        Grid.Row="2"
                        Margin="0,30,0,0"
                        Background="{DynamicResource MaterialDesignTextFieldBoxBackground}"
                        Style="{StaticResource MaterialDesignIconButton}"
                        ToolTip="MaterialDesignIconButton">
                        <materialDesign:PackIcon Foreground="White" Kind="{Binding ExitMenuBar.Icon}" />
                    </Button>

                </Grid>
            </materialDesign:Card>


            <!--  顶部菜单栏 和 主体区域  -->
            <Border
                Grid.Column="1"
                Margin="0,10"
                Background="#ffffff" />
            <Grid Grid.Column="1" Margin="0,10,0,10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>


                <!--  顶部菜单栏  -->
                <materialDesign:ColorZone
                    Name="TopMenu"
                    Grid.Row="0"
                    Height="60"
                    Background="#38B290"
                    CornerRadius="2">
                    <DockPanel>


                        <!--  最右区域  -->
                        <StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
                            <!--  头像  -->
                            <materialDesign:PopupBox>
                                <!--  图钉 设置为图片  -->
                                <materialDesign:PopupBox.ToggleContent>
                                    <Image
                                        Width="40"
                                        Height="40"
                                        Margin="5"
                                        Source="/Source/Images/user.jpeg">
                                        <Image.Clip>
                                            <EllipseGeometry
                                                Center="20,20"
                                                RadiusX="20"
                                                RadiusY="20" />
                                        </Image.Clip>
                                    </Image>

                                </materialDesign:PopupBox.ToggleContent>
                            </materialDesign:PopupBox>

                            <!--  用户名  -->
                            <TextBlock
                                Margin="0,0,10,0"
                                VerticalAlignment="Center"
                                FontSize="13"
                                Foreground="White"
                                Text="Admin...." />
                            <Button
                                Name="winMinBtn"
                                Height="auto"
                                Padding="15,0"
                                Style="{StaticResource MaterialDesignFlatButton}"
                                ToolTip="MaterialDesignFlatButton">
                                <materialDesign:PackIcon Foreground="White" Kind="WindowMinimize" />
                            </Button>

                            <Button
                                Name="winMaxBtn"
                                Height="auto"
                                Padding="15,0"
                                Style="{StaticResource MaterialDesignFlatButton}"
                                ToolTip="MaterialDesignFlatButton">
                                <materialDesign:PackIcon
                                    Name="maxBtnIcon"
                                    Foreground="White"
                                    Kind="WindowMaximize" />
                            </Button>
                            <Button
                                Name="winCloseBtn"
                                Height="auto"
                                Margin="0"
                                Padding="15,0"
                                Style="{StaticResource MaterialDesignFlatButton}"
                                ToolTip="MaterialDesignFlatButton">
                                <materialDesign:PackIcon Foreground="White" Kind="WindowClose" />
                            </Button>
                        </StackPanel>

                        <!--  最左区域  -->
                        <StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
                            <materialDesign:PackIcon
                                Width="40"
                                Height="30"
                                Margin="15,0,0,0"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Foreground="White"
                                Kind="ShieldHome" />
                            <TextBlock
                                VerticalAlignment="Center"
                                FontSize="19"
                                Foreground="White"
                                Text="智慧小区安防系统" />
                        </StackPanel>


                        <!--  导航日志区域  -->
                        <StackPanel
                            Margin="60,0,0,0"
                            VerticalAlignment="Center"
                            materialDesign:RippleAssist.IsCentered="True"
                            DockPanel.Dock="Left"
                            Orientation="Horizontal">


                            <Button
                                Width="30"
                                Height="30"
                                Margin="0,0,5,0"
                                Background="{DynamicResource MaterialDesignTextFieldBoxBackground}"
                                Command="{Binding NavigateLoggingCommand}"
                                CommandParameter="Left"
                                Style="{StaticResource MaterialDesignIconButton}"
                                ToolTip="MaterialDesignIconButton">
                                <materialDesign:PackIcon Foreground="#ffffff" Kind="ChevronLeft" />
                            </Button>


                            <Button
                                Width="30"
                                Height="30"
                                Margin="5,0,0,0"
                                Background="{DynamicResource MaterialDesignTextFieldBoxBackground}"
                                Command="{Binding NavigateLoggingCommand}"
                                CommandParameter="Right"
                                Style="{StaticResource MaterialDesignIconButton}"
                                ToolTip="MaterialDesignIconButton">

                                <materialDesign:PackIcon Foreground="#ffffff" Kind="ChevronRight" />
                            </Button>
                        </StackPanel>

                    </DockPanel>
                </materialDesign:ColorZone>

                <!--  主体区域  -->
                <ContentControl Grid.Row="1" prism:RegionManager.RegionName="MainContentRegion" />
            </Grid>


        </Grid>
    </Border>

</Window>