(三)登录模块实现

1.整改login页面加载方式

1.1符合MVVM

用事件触发器绑定命令来代替直接执行load事件绑定的方法

  • 引入xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
  • 删掉load事件,新增behaviors触发器
 <i:Interaction.Triggers>
     <i:EventTrigger EventName="Loaded">
         <i:InvokeCommandAction Command="{Binding LoadedCommand}" />
     </i:EventTrigger>
 </i:Interaction.Triggers>
  • MainWindow中方法删掉,在view model中
    image
  • 导航区域名字最好把页面名称都封装起来调用
    image

1.2 prism框架服务的不同使用方式

也可以不在构造函数依赖注入,采取下面那种方式
image
但这种方法违反了IOC容器的使用思想

2.用户登录

2.1 创建实体类user

image

2.2 前台页面的绑定

image

2.3 ReactiveObject

ReactiveUI是一个高级的、可组合的、功能反应式的模型-视图-视图模型(MVVM)框架,适用于所有.NET平台。它受到了函数式反应式编程范式的启发。
reactiveui手册
ReactiveObject可以通过注解实现通知更新的功能
image

2.4 验证通过后的页面跳转

通过事件聚合器实现

  • 在share模块添加事件
    image
  • 在验证通过后发布一个事件
    image
  • 在加载主窗体load方法中订阅事件,生成回调函数
    image
  • 当这个事件触发后运行这个回调函数
  private void OnLogined(CurrentUser user)
  {
      //加载主界面
      PrismProvider.ModuleManager.LoadModule(ModuleNames.ApplicationMainModule);//这里是仅仅传递了字符串,但是这个类继承了imodule,会通过名称找到这个类

      //导航到主区域
      PrismProvider.RegionManager.RequestNavigate(RegionNames.MainRegion, ViewNames.MainView);
  }

3.自定义控件的写法

当验证信息错误时,弹出提示,然后慢慢自己消失

3.1 新建wpf用户控件

Popup 控件提供一种在单独窗口中显示内容的方法,该窗口相对于指定元素或屏幕坐标在当前应用程序窗口上浮动。
popup介绍

  • 用户控件的修改
    image
    image

文本绑定:
Text="{Binding Path=Message,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:PopupBox},UpdateSourceTrigger=PropertyChanged}"

  • 有2个属性
  public new double Opacity//new 添加了 即隐藏了uielement中的透明度
  {
      get { return (double)GetValue(OpacityProperty); }
      set { SetValue(OpacityProperty, value); }
  }

  // 设置亮度1.0
  public static new readonly DependencyProperty OpacityProperty =
      DependencyProperty.Register("Opacity", typeof(double), typeof(PopupBox), new PropertyMetadata(1.0,new PropertyChangedCallback(OnOpacityPropertyChangedCallback)));

  /// <summary>
  /// 上面属性更新的回调函数
  /// </summary>
  /// <param name="d"></param>
  /// <param name="e"></param>
  private static void OnOpacityPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
      if (!(d is PopupBox box)) return;
      if (!(e.NewValue is double v)) return;
      box.border.Opacity = v;//赋值新的透明度
  }
  
    public string Message
  {
      get { return (string)GetValue(MessageProperty); }
      set { SetValue(MessageProperty, value); }
  }

  // Using a DependencyProperty as the backing store for Message.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty MessageProperty =
      DependencyProperty.Register("Message", typeof(string), typeof(PopupBox), new PropertyMetadata(string.Empty));
  • d is PopupBox box判断并赋值
  • 弹出方法(时间间隔是传入的)
               public static void Show(string message,Window owner=null,int seconds = 1)
        {
            try
            {
                Application.Current.Dispatcher.Invoke(new Action(() =>
                {
                    if (owner != null)
                    {
                        owner = Application.Current.MainWindow;
                    }

                    dialog.Message = message;
                    dialog.PlacementTarget = owner;//投放目标窗体
                    dialog.Placement = PlacementMode.Center;//位置居中
                    dialog.StaysOpen = true;//Popup控件会一直显示,直到显式地将IsOpen属性设置为False。如果将Popup.StaysOpen属性设置为False,当用户在其他地方单击鼠标时,Popup控件就会消失。
                    dialog.AllowsTransparency = true;//该值指示窗口的工作区是否支持透明度
                    dialog.VerticalOffset = owner.ActualHeight / 3;//垂直偏移,目标窗体的1/3
                    dialog.Opacity = 0.9;//透明度
                    dialog.IsOpen = true;//是否打开

                    //dialog显示后一秒慢慢消失
                    timer.Tick -= Timer_Tick;
                    timer.Tick += Timer_Tick;
                    timer.Interval = new TimeSpan(0, 0, seconds);
                    timer.Start();
                }));
            }
            catch(Exception ex)
            {

            }
        }

3.2 Dispatcher

dispatcher类
Wpf中Dispatcher.Invoke和Dispatcher.BeginInvoke的区别

            new Thread(()=> {
                Application.Current.Dispatcher.BeginInvoke(new Action(() => {
                    while (true)
                    {
                        Thread.Sleep(1000);
                    }
                }), null);
                Console.WriteLine("test");
 
            }).Start();

这段代码,会在控制台打印test,然后界面会一直卡住。界面卡住,说明while循环是在ui线程执行的,能够打印test,说明在执行Application.Current.Dispatcher.BeginInvoke时并没有阻塞当前界面,如果把BeginInvoke改成Invoke,那么test将不会被打印,说明Invoke方法的逻辑是把委托交给ui线程执行,并阻塞当前线程,直到委托结束。而BeginInvoke方法则首先新开一个线程,那新开的线程,再将委托交给ui线程处理。注意,最终执行委托的线程都是ui线程。所以,BeginInvoke由于有个新开线程的过程,不会阻塞当前线程。但仍然会阻塞界面。

3.3 事件控制透明度

 private static void Timer_Tick(object sender, EventArgs e)
 {
     timer.Stop();
     Task.Run(() =>
     {
         try
         {
             for (int i = 0; i < 100; i++)
             {
                 Thread.Sleep(5);
                 if (Application.Current == null) return;   //Application.Current==>shell.app
                 Application.Current.Dispatcher.Invoke(() => 
                 {
                     dialog.Opacity -= 0.01;
                 });
             }

             //透明度减完,把显示关闭,信息清空
             Application.Current.Dispatcher.Invoke(() =>
             {
                 dialog.IsOpen = false;
                 dialog.Message=string.Empty;
             });
         }
         catch (Exception ex)
         {

         }
     });
 }

3.4 使用

image

posted @ 2023-11-16 09:39  huihui不会写代码  阅读(178)  评论(0)    收藏  举报