WPF 登錄菜單頁面跳轉

先上界面效果圖:

在這裏插入圖片描述

該項目包含了根據背景圖片等比放置控件、登錄頁面、登錄跳轉、以及後續菜單的頁面跳轉功能

MainWindow:

<Window x:Class="LogInDemo.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:local="clr-namespace:LogInDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None" ResizeMode="NoResize">
    <Window.DataContext>
        <local:MainWindowViewModel></local:MainWindowViewModel>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Height="30">
            <Grid.Background>
                <SolidColorBrush Color="Orange"></SolidColorBrush>
            </Grid.Background>
            <Button Width="50" Height="25" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0" Content="首頁" Background="CadetBlue" Foreground="Red" Command="{Binding HomePageCmd}"></Button>
            <Button Width="25" Height="25" HorizontalAlignment="Right" Margin="10,0" Background="Orange" BorderThickness="0" Content="X" Cursor="Hand" Click="Button_Click"></Button>
        </Grid>
        <ContentControl x:Name="ViewControl" Content="{Binding ViewControl}" Grid.Row="1"/>
    </Grid>
</Window>

MainWindowViewModel:

using LogInDemo.Model;
using LogInDemo.View;
using LogInDemo.ViewModel;
using System.Windows.Controls;
using System.Windows.Input;

namespace LogInDemo
{
    public class MainWindowViewModel : ViewModelBase
    {

        LogInControl logInView;
        MenuPage menuView;
        ViewA viewA;
        ViewB viewB;
        ViewC viewC;
        ViewD viewD;
        public MainWindowViewModel()
        {
            //初始化主窗體,當前運行的顯示頁爲登錄頁面
            logInView = new LogInControl();
            menuView = new MenuPage();
            viewA = new ViewA();
            viewB = new ViewB();
            viewC = new ViewC();
            viewD = new ViewD();
            ViewControl = new Frame()
            {
                Content = logInView
            };
            MessageAggregator<object>.Instance.Subscribe("PageChanged", ToggleHandler);
            HomePageCmd = new RelayCommand(ViewToHomePage);
        }
        public ICommand HomePageCmd { get; }

        private void ToggleHandler(object sender, MessageArgs<object> args)
        {
            string getPageName = (string)args.Item;
            switch (getPageName)
            {
                case "MenuPage":
                    ViewControl = new Frame()
                    {
                        Content = menuView
                    };
                    break;
                case "ViewA":
                    ViewControl = new Frame()
                    {
                        Content = viewA
                    };
                    break;
                case "ViewB":
                    ViewControl = new Frame()
                    {
                        Content = viewB
                    };
                    break;
                case "ViewC":
                    ViewControl = new Frame()
                    {
                        Content = viewC
                    };
                    break;
                case "ViewD":
                    ViewControl = new Frame()
                    {
                        Content = viewD
                    };
                    break;
            }
        }

        private object _contentControl;
        public object ViewControl
        {
            get
            { return _contentControl; }

            set
            {
                _contentControl = value;
                RaisePropertyChanged("ViewControl");
            }
        }

        private void ViewToHomePage()
        {
            ViewControl = new Frame()
            {
                Content = menuView
            };
        }
    }
}

LogInControl:
根據背景圖片等比放置控件,根據背景圖片的實際情況進行行列的距離等比定義

<UserControl x:Class="LogInDemo.LogInControl"
        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:local="clr-namespace:LogInDemo"
        xmlns:Core="clr-namespace:LogInDemo"
        mc:Ignorable="d"
        d:DesignHeight="600" d:DesignWidth="800">
    <UserControl.Background>
        <ImageBrush ImageSource="/Resource/LogIn.jpg"></ImageBrush>
    </UserControl.Background>
    <UserControl.DataContext>
        <local:LogInControlViewModel/>
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="130*"/>
            <RowDefinition Height="340*"/>
            <RowDefinition Height="130*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="220*"/>
                <ColumnDefinition Width="350*"/>
                <ColumnDefinition Width="230*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="30*"/>
                    <ColumnDefinition Width="290*"/>
                    <ColumnDefinition Width="30*"/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="105*"/>
                        <RowDefinition Height="55*"/>
                        <RowDefinition Height="55*"/>
                        <RowDefinition Height="33*"/>
                        <RowDefinition Height="60*"/>
                        <RowDefinition Height="32*"/>
                    </Grid.RowDefinitions>
                    <Grid Grid.Row="1">
                        <TextBox x:Name="IDTextBox" Text="{Binding AccountNumber, UpdateSourceTrigger=PropertyChanged}" 
                                     Background="Transparent" BorderThickness="0" 
                                     Foreground="OrangeRed" 
                                     CaretBrush="OrangeRed" 
                                     VerticalAlignment="Center" 
                                     VerticalContentAlignment="Stretch" Margin="20,0,0,0"/>
                        <TextBlock IsHitTestVisible="False" 
                                       Text="請輸入賬號" 
                                       Foreground="DarkGray" 
                                       Background="Transparent"
                                       VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20,0,0,0">
                            <TextBlock.Style>
                                <Style TargetType="{x:Type TextBlock}">
                                    <Setter Property="Visibility" Value="Collapsed"/>
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Text, ElementName=IDTextBox}" Value="">
                                            <Setter Property="Visibility" Value="Visible"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBlock.Style>
                        </TextBlock>
                    </Grid>
                    <Grid Grid.Row="2">
                        <PasswordBox Tag="請輸入密碼" 
                                         x:Name="PassWordTextBox" 
                                         Background="Transparent" 
                                         BorderThickness="0" 
                                         VerticalAlignment="Center" 
                                         HorizontalAlignment="Left"
                                         VerticalContentAlignment="Stretch"
                                         Core:PasswordBoxHelper.Password="{Binding Path=PassWordValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Margin="20,0,0,0">
                            <PasswordBox.Style>
                                <Style TargetType="PasswordBox">
                                    <Setter Property="Foreground" Value="OrangeRed"/>
                                    <Setter Property="Core:PasswordBoxHelper.IsMonitoring" Value="true"/>
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type PasswordBox}">
                                                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                                    <Grid>
                                                        <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                                                        <TextBlock x:Name="WaterMark" Focusable="False" Visibility="Collapsed" Text="{TemplateBinding Tag}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                                                    </Grid>
                                                </Border>
                                                <ControlTemplate.Triggers>
                                                    <Trigger Property="Core:PasswordBoxHelper.PasswordLength" Value="0">
                                                        <Setter TargetName="WaterMark" Property="Visibility" Value="Visible"/>
                                                        <Setter TargetName="WaterMark" Property="Foreground" Value="DarkGray"/>
                                                    </Trigger>
                                                </ControlTemplate.Triggers>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </PasswordBox.Style>
                        </PasswordBox>
                    </Grid>
                    <Grid Grid.Row="4">
                        <Button x:Name="btn_Login" Command="{Binding LoginCmd}" Background="Orange" BorderThickness="0" IsDefault="True"
                    Content="登錄" Grid.Column="1" Template="{DynamicResource ButtonBaseControlTemplate1}" Foreground="White">
                            <Button.Resources>
                                <ControlTemplate x:Key="ButtonBaseControlTemplate1" TargetType="{x:Type ButtonBase}">
                                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                        <TextBlock x:Name="contentPresenter" FontSize="20px" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Content}" />
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <Trigger Property="Button.IsDefaulted" Value="True">
                                            <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                        </Trigger>
                                        <Trigger Property="IsMouseOver" Value="True">
                                            <Setter Property="Background" TargetName="border" Value="#173060"/>
                                            <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
                                        </Trigger>
                                        <Trigger Property="ToggleButton.IsChecked" Value="True">
                                            <Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
                                            <Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
                                        </Trigger>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="Background" TargetName="border" Value="#E2E2E2" />
                                            <Setter Property="Foreground" TargetName="contentPresenter" Value="#919191" />
                                            <Setter Property="Text" TargetName="contentPresenter" Value="登錄中..." />
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Button.Resources>
                        </Button>
                    </Grid>
                </Grid>
            </Grid>
        </Grid>
    </Grid>
</UserControl>

LogInControlViewModel:

using LogInDemo.Model;
using LogInDemo.ViewModel;
using System.Threading.Tasks;
using System.Windows.Input;

namespace LogInDemo
{
    public class LogInControlViewModel: ViewModelBase
    {
        public LogInControlViewModel()
        {
            LoginCmd = new RelayCommand(PressOK, () => !IsLoadding);
        }

        private string _accountNumber;
        public string AccountNumber
        {
            get
            { return _accountNumber; }

            set
            {
                _accountNumber = value;
                RaisePropertyChanged("AccountNumber");
            }
        }

        private string _passWordValue;
        public string PassWordValue
        {
            get
            { return _passWordValue; }

            set
            {
                _passWordValue = value;
                RaisePropertyChanged("PassWordValue");
            }

        }

        private bool _isLoadding;
        public bool IsLoadding
        {
            get
            { return _isLoadding; }

            set
            {
                _isLoadding = value;
                RaisePropertyChanged("IsLoadding");
            }

        }

        public ICommand LoginCmd { get; }

        private bool CanPreess()
        {
            return IsLoadding;
        }

        private async void PressOK()
        {
            IsLoadding = true;
            await Init();  //登陸延時,在此處初始化登陸時的耗時操作
            MessageAggregator<object>.Instance.Publish("PageChanged", this, new MessageArgs<object>("MenuPage"));
            IsLoadding = false;
        }

        private Task Init()
        {
            return Task.Factory.StartNew(DoInit);
        }

        private void DoInit()
        {
            System.Threading.Thread.Sleep(1000);
        }
    }
}

PasswordBoxHelper:
Password水印效果和綁定值的輔助類

using System.Windows;
using System.Windows.Controls;

namespace LogInDemo
{
    /// <summary>
    /// PasswordBox添加水印輔助類
    /// </summary>
    public class PasswordBoxHelper : DependencyObject
    {
        public static bool GetIsMonitoring(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsMonitoringProperty);
        }

        public static void SetIsMonitoring(DependencyObject obj, bool value)
        {
            obj.SetValue(IsMonitoringProperty, value);
        }

        public static readonly DependencyProperty IsMonitoringProperty =
            DependencyProperty.RegisterAttached("IsMonitoring", typeof(bool), typeof(PasswordBoxHelper), new UIPropertyMetadata(false, OnIsMonitoringChanged));

        public static readonly DependencyProperty PasswordProperty =
              DependencyProperty.RegisterAttached("Password",
              typeof(string), typeof(PasswordBoxHelper),
              new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));

        public static int GetPasswordLength(DependencyObject obj)
        {
            return (int)obj.GetValue(PasswordLengthProperty);
        }

        public static void SetPasswordLength(DependencyObject obj, int value)
        {
            obj.SetValue(PasswordLengthProperty, value);
        }

        public static readonly DependencyProperty PasswordLengthProperty =
            DependencyProperty.RegisterAttached("PasswordLength", typeof(int), typeof(PasswordBoxHelper), new UIPropertyMetadata(0));

        private static readonly DependencyProperty IsUpdatingProperty =
           DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
           typeof(PasswordBoxHelper));

        public static readonly DependencyProperty AttachProperty =
              DependencyProperty.RegisterAttached("Attach",
              typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, Attach));

        private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var pb = d as PasswordBox;
            if (pb == null)
            {
                return;
            }
            if ((bool)e.NewValue)
            {
                pb.PasswordChanged += PasswordChanged;
            }
            else
            {
                pb.PasswordChanged -= PasswordChanged;
            }
        }

        public static void SetAttach(DependencyObject dp, bool value)
        {
            dp.SetValue(AttachProperty, value);
        }
        public static bool GetAttach(DependencyObject dp)
        {
            return (bool)dp.GetValue(AttachProperty);
        }
        public static string GetPassword(DependencyObject dp)
        {
            return (string)dp.GetValue(PasswordProperty);
        }
        public static void SetPassword(DependencyObject dp, string value)
        {
            dp.SetValue(PasswordProperty, value);
        }

        private static bool GetIsUpdating(DependencyObject dp)
        {
            return (bool)dp.GetValue(IsUpdatingProperty);
        }
        private static void SetIsUpdating(DependencyObject dp, bool value)
        {
            dp.SetValue(IsUpdatingProperty, value);
        }

        private static void OnPasswordPropertyChanged(DependencyObject sender,
                     DependencyPropertyChangedEventArgs e)
        {
            PasswordBox passwordBox = sender as PasswordBox;
            passwordBox.PasswordChanged -= PasswordChanged;
            if (!(bool)GetIsUpdating(passwordBox))
            {
                passwordBox.Password = (string)e.NewValue;
            }
            passwordBox.PasswordChanged += PasswordChanged;
        }

        private static void Attach(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            PasswordBox passwordBox = sender as PasswordBox;
            if (passwordBox == null)
                return;
            if ((bool)e.OldValue)
            {
                passwordBox.PasswordChanged -= PasswordChanged;
            }
            if ((bool)e.NewValue)
            {
                passwordBox.PasswordChanged += PasswordChanged;
            }
        }

        private static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            var passwordBox = sender as PasswordBox;
            if (passwordBox == null)
            {
                return;
            }
            SetPasswordLength(passwordBox, passwordBox.Password.Length);
            SetIsUpdating(passwordBox, true);
            SetPassword(passwordBox, passwordBox.Password);
            SetIsUpdating(passwordBox, false);
        }
    }
}

MenuPage:
登錄後的菜單頁面跳轉

<UserControl x:Class="LogInDemo.MenuPage"
             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:LogInDemo"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="500">
    <UserControl.DataContext>
        <local:MenuPageViewModel></local:MenuPageViewModel>
    </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Button Content="This is First Menu" Grid.Column="0" Grid.Row="0" Foreground="Red" Command="{Binding ChangeViewACmd}"></Button>
        <Button Content="This is Second Menu" Grid.Column="1" Grid.Row="0" Foreground="Red" Command="{Binding ChangeViewBCmd}"></Button>
        <Button Content="This is Third Menu" Grid.Column="0" Grid.Row="1" Foreground="Red" Command="{Binding ChangeViewCCmd}"></Button>
        <Button Content="This is Fourth Menu" Grid.Column="1" Grid.Row="1" Foreground="Red" Command="{Binding ChangeViewDCmd}"></Button>
    </Grid>
</UserControl>

MenuPageViewModel:

using LogInDemo.Model;
using LogInDemo.ViewModel;
using System.Threading.Tasks;
using System.Windows.Input;

namespace LogInDemo
{
    public class MenuPageViewModel : ViewModelBase
    {
        public MenuPageViewModel()
        {
            ChangeViewACmd = new RelayCommand(ChangeViewA);
            ChangeViewBCmd = new RelayCommand(ChangeViewB);
            ChangeViewCCmd = new RelayCommand(ChangeViewC);
            ChangeViewDCmd = new RelayCommand(ChangeViewD);
        }

        public ICommand ChangeViewACmd { get; }
        public ICommand ChangeViewBCmd { get; }
        public ICommand ChangeViewCCmd { get; }
        public ICommand ChangeViewDCmd { get; }

        private void ChangeViewA()
        {
            MessageAggregator<object>.Instance.Publish("PageChanged", this, new MessageArgs<object>("ViewA"));
        }

        private void ChangeViewB()
        {
            MessageAggregator<object>.Instance.Publish("PageChanged", this, new MessageArgs<object>("ViewB"));
        }

        private void ChangeViewC()
        {
            MessageAggregator<object>.Instance.Publish("PageChanged", this, new MessageArgs<object>("ViewC"));
        }

        private void ChangeViewD()
        {
            MessageAggregator<object>.Instance.Publish("PageChanged", this, new MessageArgs<object>("ViewD"));
        }
    }
}

用於頁面跳轉的消息通知類 MessageAggregator:

using System.Collections.Generic;

namespace LogInDemo.Model
{
    public delegate void MessageHandler<T>(object sender, MessageArgs<T> args);
    public class MessageAggregator<T>
    {
        private readonly Dictionary<string, MessageHandler<T>> _messages = new Dictionary<string, MessageHandler<T>>();

        public static readonly MessageAggregator<T> Instance = new MessageAggregator<T>();

        private MessageAggregator()
        {

        }

        public void Subscribe(string name, MessageHandler<T> handler)
        {
            if (!_messages.ContainsKey(name))
            {
                _messages.Add(name, handler);
            }
            else
            {
                _messages[name] += handler;
            }

        }
        public void Publish(string name, object sender, MessageArgs<T> args)
        {
            if (_messages.ContainsKey(name) && _messages[name] != null)
            {
                //轉發
                _messages[name](sender, args);
            }
        }

    }

    public class MessageArgs<T>
    {
        public T Item { get; set; }
        public MessageArgs(T item)
        {
            Item = item;
        }
    }
}

剩下四個頁面 ViewA、ViewB、ViewC、ViewD、爲四個只放了一個Textblock的空頁面就不上代碼了。

參考:https://www.cnblogs.com/su-yang/p/7009956.html
https://yq.aliyun.com/articles/389853

源碼:放在CSDN下載了 點擊此下載源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章