一起谈.NET技术,Silverlight实例教程 - Out of Browser音乐播放器

简介:   Silverlight 实例教程索引Silverlight 实例教程 - Out of Browser开篇Silverlight 实例教程 - Out of Browser配置,安装和卸载Silverlight 实例教程 - Out of Browser的自定义应用Silverligh...

  Silverlight 实例教程索引

  本篇,我们将结合以往的Out of Browser特性,创建一款新的Out of Browser实例, 音乐播放器。 该实例目的比较简单,实现音乐播放,实现音乐文件列表读取,实现音乐文件信息读取,另外音乐播放自动跳转等功能。

  在实例开始前,我们仍旧需要了解一些基础知识。Silverlight对音频的支持是使用MediaElement类,该类使用方法非常简单,该类的详细解释,请看MSDN

1  < MediaElement 
2       x:Name ="media"  
3      Source ="xbox.wmv"  
4      CurrentStateChanged ="media_state_changed"  
5      Width ="300"  Height ="300" />

  在了解了音频播放类的简单使用后,让我们先看看项目完成后的效果图。

  从上面效果图中可以看出整个实例项目UI分5个部分:

  1. 音频控制部分,这部分是实例主要功能;

  2. 音频文件信息部分,这部分是获取显示当前和下一首音乐文件信息;

  3. 唱片图片信息,其实这部分也是属于音频文件信息,不过这里单独列出来,使用独立的类进行处理;

  4. 音频文件列表,该列表是载入My Music目录中的音乐文件,并支持用户选择播放功能;

  5. UI控制,该部分可以使播放器进入最小化状态。例如:

  下面我们开始分别解释以上几个部分的实例设计方法。

  我们仍旧使用SilverlightOOBDemo项目,不过为了使代码更清晰易读,这次不再使用OutofBrowserMainPage作为OOB应用主界面,我们重新创建一个新的OOB应用界面OutofBrowserMusicPlayer。

  为了修改启动页面为OutofBrowserMusicPlayer,为此,我们需要修改App.xaml中的启动页面代码:

 1  private   void  Application_Startup( object  sender, StartupEventArgs e)
 2  {
 3               if  ( ! Application.Current.IsRunningOutOfBrowser)
 4              {
 5                   this .RootVisual  =   new  MainPage();
 6              }
 7               else
 8              {
 9                   // this.RootVisual = new OutofBrowserMainPage();
10                     this .RootVisual  =   new  OutofBrowserMusicPlayer();
11              }
12              
13  }

  根据实例需求,我们最主要的功能就是播放音乐,所以,我们第一步首先实现Out of Browser应用音频控制。

  1. 创建自定义音频控制控件;

  对于音频控制,这里我们使用了自定义控件控制音乐的播放。AudioControl.xaml控件。

  
这里我仅贴上部分代码,大家可以在文章最后下载完整源代码。
 1  < Grid  x:Name ="LayoutRoot" >
 2           < Grid.ColumnDefinitions >
 3               < ColumnDefinition  Width ="Auto"   />
 4               < ColumnDefinition  Width ="*"   />
 5               < ColumnDefinition  Width ="25"   />
 6               < ColumnDefinition  Width ="Auto"   />
 7               < ColumnDefinition  Width ="Auto"   />
 8           </ Grid.ColumnDefinitions >
 9           < Grid  Grid.Column ="0"  Margin ="0,0,0,0"  HorizontalAlignment ="Left"  VerticalAlignment ="Center"  x:Name ="gridCol1" >
10               < ToggleButton  Cursor ="Hand"  Margin ="0,0,0,0"  x:Name ="btnPlay"  RenderTransformOrigin ="0.5,0.5"  Template =" {StaticResource playControlTemplate} " >
11                   < ToggleButton.RenderTransform >
12                       < TransformGroup >
13                           < ScaleTransform  ScaleX ="1"  ScaleY ="1" />
14                           < SkewTransform />
15                           < RotateTransform />
16                           < TranslateTransform />
17                       </ TransformGroup >
18                   </ ToggleButton.RenderTransform >
19               </ ToggleButton >
20           </ Grid >
21           < Grid  Grid.Column ="1"  Margin ="0,0,0,0"  HorizontalAlignment ="Stretch"  x:Name ="gridCol2"  VerticalAlignment ="Center" >
22               < Grid.ColumnDefinitions >
23                   < ColumnDefinition  Width ="*"   />
24                   < ColumnDefinition  Width ="40"   />
25                   < ColumnDefinition  Width ="10"   />
26                   < ColumnDefinition  Width ="40"   />
27               </ Grid.ColumnDefinitions >
28               < TextBlock  x:Name ="tbCurrentTime"  Margin ="0,1.5,0,0"   Height ="12"  FontFamily ="Verdana"  FontSize ="10"  Text ="00:00"  TextWrapping ="Wrap"  Foreground ="#FFFFFFFF"  FontStyle ="Normal"  HorizontalAlignment ="Right"  TextAlignment ="Right"  Grid.Column ="1" />
29               < TextBlock  Margin ="0,1.5,0,0"   Height ="12"  FontFamily ="Verdana"  FontSize ="10"  Text ="/"  TextWrapping ="Wrap"  Foreground ="#FFFFFFFF"  FontStyle ="Normal"  HorizontalAlignment ="Center"  TextAlignment ="Right"  Grid.Column ="2" />
30               < TextBlock  x:Name ="tbTotalTime"  Margin ="0,1.5,0,0"   Height ="12"  FontFamily ="Verdana"  FontSize ="10"  Text ="00:00"  TextWrapping ="Wrap"  Foreground ="#FFFFFFFF"  FontStyle ="Normal"  HorizontalAlignment ="Left"  TextAlignment ="Right"  Grid.Column ="3" />
31               < local:MediaSlider  Margin ="0,1.5,0,0"  HorizontalAlignment ="Stretch"  Maximum ="100"  x:Name ="sliderTimeline"  Style =" {StaticResource progressSliderStyle} "  Grid.Column ="0"  Value ="0"  Visibility ="Visible" />
32           </ Grid >
33           < Grid  Grid.Column ="2"  Margin ="4,0,4,0"  HorizontalAlignment ="Stretch"  x:Name ="gridCol3"  VerticalAlignment ="Center" >
34               < local:Spinner  Margin ="0,0,0,0"  x:Name ="spinner"  Width ="17"  Height ="17"  HorizontalAlignment ="Center"  VerticalAlignment ="Center" />
35           </ Grid >
36           < Grid  Grid.Column ="3"  Margin ="0,10.30,0,10.30"  HorizontalAlignment ="Stretch"  x:Name ="gridCol4"  Width ="70"  VerticalAlignment ="Stretch"  d:LayoutOverrides ="Height" >
37               < Grid  Margin ="0,0,0,0"  HorizontalAlignment ="Right"  VerticalAlignment ="Center"  Width ="70" >
38                   < Grid.ColumnDefinitions >
39                       < ColumnDefinition  Width ="Auto"   />
40                       < ColumnDefinition  Width ="*"   />
41                   </ Grid.ColumnDefinitions >
42                   < ToggleButton  HorizontalAlignment ="Left"  IsChecked ="True"  Margin ="0,0,0,0"  x:Name ="btnSpeaker"  Template =" {StaticResource speakerControlTemplate} " />
43                   < Slider  Grid.Column ="1"  HorizontalAlignment ="Stretch"  Margin ="3,0,0,0"  VerticalAlignment ="Center"  Maximum ="1"  x:Name ="sliderVolume"  Style =" {StaticResource volumeSliderStyle} "  Background ="#FF777777" />
44               </ Grid >
45           </ Grid >
46           < Grid  Grid.Column ="4"  Margin ="0,10.3120002746582,4,10.3120002746582"  HorizontalAlignment ="Right"  x:Name ="gridCol5"  VerticalAlignment ="Stretch"  d:LayoutOverrides ="Height" >
47               < ToggleButton  Cursor ="Hand"  HorizontalAlignment ="Left"  Margin ="0,0,0,0"  x:Name ="btnFullScreen"  Template =" {StaticResource fullScreenControlTemplate} " />
48           </ Grid >
49       </ Grid >

 

  从以上代码可以看到,在AudioControl中有两个自定义控件local:MediaSliderlocal:Spinner

  MediaSlider:

  其功能是控制音乐播放进度,支持拖拽前进或者后退音乐播放进度。其代码如下:

  1  public   class  MediaSlider : Slider
  2      {
  3           public  Thumb              horizontalThumb;
  4           private  FrameworkElement horizontalLeftTrack;
  5           private  FrameworkElement horizontalRightTrack;
  6           private   double  oldValue  =   0 , newValue  =   0 , prevNewValue  =   0 ;
  7           public   event  RoutedPropertyChangedEventHandler < double >  MyValueChanged;
  8           public   event  RoutedPropertyChangedEventHandler < double >  MyValueChangedInDrag;
  9           private  DispatcherTimer dragtimer  =   new  DispatcherTimer();
 10           private   double  dragTimeElapsed  =   0 ;
 11           private   const   short  DragWaitThreshold  =   200 , DragWaitInterval  =   100 ;
 12           public  Rectangle progressRect  =   null ;
 13           private   bool  dragSeekJustFired  =   false ;
 14 
 15           public  MediaSlider()
 16          {
 17 
 18               this .ValueChanged  +=   new  RoutedPropertyChangedEventHandler < double > (CustomSlider_ValueChanged);
 19              dragtimer.Interval  =   new  TimeSpan( 0 0 0 0 , DragWaitInterval);
 20              dragtimer.Tick  +=   new  EventHandler(dragtimer_Tick);
 21          }
 22 
 23           void  dragtimer_Tick( object  sender, EventArgs e)
 24          {
 25              dragTimeElapsed  +=  DragWaitInterval;
 26 
 27               if  (dragTimeElapsed  >=  DragWaitThreshold)
 28              {
 29                  RoutedPropertyChangedEventHandler < double >  handler  =  MyValueChangedInDrag;
 30                  
 31                   if  ((handler  !=   null &&  (newValue  !=  prevNewValue))
 32                  {
 33                      handler( this new  RoutedPropertyChangedEventArgs < double > (oldValue, newValue));
 34                      dragSeekJustFired  =   true ;
 35                      prevNewValue  =  newValue;
 36                  }
 37 
 38                  dragTimeElapsed  =   0 ;
 39              }
 40          }
 41 
 42           void  CustomSlider_ValueChanged( object  sender, RoutedPropertyChangedEventArgs < double >  e)
 43          {
 44              oldValue  =  e.OldValue;
 45              newValue  =  e.NewValue;
 46 
 47               if  (horizontalThumb.IsDragging)
 48              {
 49                  dragTimeElapsed  =   0 ;
 50                  dragtimer.Stop();
 51                  dragtimer.Start();
 52                  dragSeekJustFired  =   false ;
 53              }
 54          }
 55 
 56           public   override   void  OnApplyTemplate()
 57          {
 58               base .OnApplyTemplate();
 59 
 60              horizontalThumb  =  GetTemplateChild( " HorizontalThumb " as  Thumb;
 61              horizontalLeftTrack  =  GetTemplateChild( " LeftTrack " as  FrameworkElement;
 62              horizontalRightTrack  =  GetTemplateChild( " RightTrack " as  FrameworkElement;
 63              progressRect  =  GetTemplateChild( " Progress " as  Rectangle;
 64 
 65               if  (horizontalLeftTrack  !=   null ) horizontalLeftTrack.MouseLeftButtonDown  +=   new  MouseButtonEventHandler(OnMoveThumbToMouse);
 66 
 67               if  (horizontalRightTrack  !=   null ) horizontalRightTrack.MouseLeftButtonDown  +=   new  MouseButtonEventHandler(OnMoveThumbToMouse);
 68 
 69              horizontalThumb.DragCompleted  +=   new  DragCompletedEventHandler(DragCompleted);
 70 
 71              progressRect.Width  =   this .Width;
 72          }
 73 
 74           public  Storyboard ProgressStoryboard {  get  {  return  (GetTemplateChild( " ProgressStoryboard " as  Storyboard); } }
 75 
 76           public  Rectangle ProgressBar {  get  {  return  (GetTemplateChild( " Progress " as  Rectangle); } }
 77 
 78           protected   override  Size ArrangeOverride(Size finalSize)
 79          {
 80              Size s  =   base .ArrangeOverride(finalSize);
 81 
 82               if  ( double .IsNaN(horizontalThumb.Width)  &&  (horizontalThumb.ActualWidth  !=   0 ))
 83              {
 84                  horizontalThumb.Width  =  horizontalThumb.ActualWidth;
 85              }
 86 
 87               if  ( double .IsNaN(horizontalThumb.Height)  &&  (horizontalThumb.ActualHeight  !=   0 ))
 88              {
 89                  horizontalThumb.Height  =  horizontalThumb.ActualHeight;
 90              }
 91 
 92               if  ( double .IsNaN(horizontalThumb.Width)) horizontalThumb.Width  =  horizontalThumb.Height;
 93               if  ( double .IsNaN(horizontalThumb.Height)) horizontalThumb.Height  =  horizontalThumb.Width;
 94 
 95               return  (s);
 96          }
 97          
 98           private   void  OnMoveThumbToMouse( object  sender, MouseButtonEventArgs e)
 99          {
100              e.Handled  =   true ;
101              Point p  =  e.GetPosition( this );
102 
103               if  ( this .Orientation  ==  Orientation.Horizontal)
104              {
105                  Value  =  (p.X  -  (horizontalThumb.ActualWidth  /   2 ))  /  (ActualWidth  -  horizontalThumb.ActualWidth)  *  Maximum;
106              }
107 
108              RoutedPropertyChangedEventHandler < double >  handler  =  MyValueChanged;
109 
110               if  (handler  !=   null )
111              {
112                  handler( this new  RoutedPropertyChangedEventArgs < double > (oldValue, Value));
113              }
114          }
115 
116           private   void  DragCompleted( object  sender, DragCompletedEventArgs e)
117          {
118              dragtimer.Stop();
119              dragTimeElapsed  =   0 ;
120 
121              RoutedPropertyChangedEventHandler < double >  handler  =  MyValueChanged;
122 
123               if  ((handler  !=   null &&  ( ! dragSeekJustFired))
124              {
125                  handler( this new  RoutedPropertyChangedEventArgs < double > (oldValue,  this .Value));
126              }
127          }
128      }

  而Spinner控件,是一个载入标识,当音频载入时,会显示该控件。该控件为Path绘制的控件,这里不再贴出代码描述。

  2. 获取音频文件信息部分

  该部分我们同样也创建一个自定义控件来实现,TrackInfo.xaml,主要是负责在客户端显示音频文件的信息,而Silverlight没有相关API可以实现读取音频文件的标签信息,这里,我们需要引入一个微软开源类库TagLib。该类库的主要功能就是读取和修改音乐文件的标签信息。

  其调用方法非常简单:

1  //  获取标签
2    tags  =  TagLib.File.Create(MediaFile.ID);
3    //  设置标签属性
4    MediaFile.Artist  =  tags.Tag.FirstPerformer;
5  MediaFile.Title  =  tags.Tag.Title;
6  MediaFile.Album  =  tags.Tag.Album;
7  MediaFile.Genre  =  tags.Tag.FirstGenre;

  当音乐标签信息获取成功后,即可将信息绑定到TrackInfo.DataContext。

  3. 唱片图片信息

  对于唱片的图片信息,这里需要读取Image从本地目录,当没有唱片图片时,则显示默认Music.png图片。这里需要注意的是,读取本地文件,需要OOB应用权限信任。

 1  public  ImageSource AlbumArtStream
 2  {
 3               get
 4              {
 5                  BitmapImage image;
 6 
 7                   if  ( string .IsNullOrEmpty(AlbumArtPath))
 8                  {
 9                       if  ( null   ==  _default)
10                      {
11                          _default  =   new  BitmapImage( new  Uri( " ../Images/Music.png " , UriKind.Relative));
12                      }
13 
14                      image  =  _default;
15                  }
16                   else
17                  {
18                      FileStream stream  =  File.Open(AlbumArtPath, FileMode.Open, FileAccess.Read);
19 
20                      image  =   new  BitmapImage();
21                      image.SetSource(stream);
22                      stream.Close();
23                  }
24 
25                   return  image;
26              }
27  }

  4. 获取音频文件列表

  从演示图片可以看出,我们的音频文件列表,是用了一个绑定了音乐播放文件信息的Datagrid。

  其代码非常简单,创建两列,分别绑定歌手和歌曲名:

 1  < data:DataGrid  x:Name ="playList"
 2                         Grid.Row ="1"
 3                         Grid.Column ="1"
 4                         Grid.RowSpan ="3"
 5                         VerticalAlignment ="Top"
 6                         Margin ="4"
 7                         Height ="296"
 8                         Style =" {StaticResource DataGridStyle} "
 9                         AutoGenerateColumns ="False"
10                         CanUserResizeColumns ="True"
11                         CanUserSortColumns ="False"
12                         SelectionChanged ="playList_SelectionChanged" >
13               < data:DataGrid.Columns >
14                   < data:DataGridTextColumn  Header ="歌手"
15                                           Binding =" {Binding Artist} "
16                                           FontSize ="12"   />
17                   < data:DataGridTextColumn  Header ="歌名"
18                                           Binding =" {Binding Title} "
19                                           FontSize ="12"
20                                           Width ="*"   />
21               </ data:DataGrid.Columns >
22    </ data:DataGrid >

  而后台,在读取了My Music目录后,将数据集绑定到datagrid.ItemsSource就可以正常实现歌曲列表了。

 1  public   static  List < MediaFile >  GetMediaFiles()
 2  {
 3              List < MediaFile >  files  =   null ; ;
 4              MediaFile mf;
 5               string  path  =  Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
 6              IEnumerable < string >  list  =  Directory.EnumerateFiles(path,  " *.mp3 " , SearchOption.AllDirectories);
 7              TagLib.File tags;
 8              files  =  GetCachedList(list);
 9               if  ( null   ==  files  ||  files.Count  ==   0 )
10              {
11                  files  =   new  List < MediaFile > ();
12                   foreach  ( string  file  in  list)
13                  {
14                      mf  =   new  MediaFile();
15                      mf.ID  =  file;
16                      mf.AlbumArtPath  =  GetAlbumArtPath(file);
17                      files.Add(mf);
18                  }
19 
20                   for  ( int  idx  =   0 ; idx  <  files.Count; idx ++ )
21                  {
22                      mf  =  files[idx];
23                      tags  =  TagLib.File.Create(mf.ID);
24                      mf.Artist  =  tags.Tag.FirstPerformer;
25                      mf.Title  =  tags.Tag.Title;
26                      mf.Album  =  tags.Tag.Album;
27                      mf.Genre  =  tags.Tag.FirstGenre;
28                  }
29                  SaveCachedList(files);
30              }
31 
32               return  files;
33  }

  在绑定成功后,同时,我们支持用户选择指定音乐播放,使用Datagrid的SelectionChanged事件即可。

 1  private   void  playList_SelectionChanged( object  sender, SelectionChangedEventArgs e)
 2  {
 3              DataGrid dg  =  (sender  as  DataGrid);
 4 
 5               if  (dg.SelectedIndex  !=  _nowPlaying)
 6              {
 7                   if  (dg.SelectedIndex  !=   0 )
 8                  {
 9                      me.AutoPlay  =   true ;
10                  }
11                  OpenAndPlay(dg.SelectedIndex);
12              }
13              
14  }

  5. UI控制

  对于UI的控制,这里我们只是简单的实现了隐藏和显示音乐信息框的功能,其代码实现:

 1           private   void  Minimize_Click( object  sender, MouseButtonEventArgs e)
 2          {
 3              Window main  =  Application.Current.MainWindow;
 4 
 5               if  ( ! _min)
 6              {
 7                  main.Height  =   40 ;
 8                  rot.Angle  =   0 ;
 9              }
10               else
11              {
12                  main.Height  =   340 ;
13                  rot.Angle  =   180 ;
14              }
15 
16              _min  =   ! _min;
17          }

  上面是OOB音乐播放器5个部分的核心功能代码,这里,我想同时将上一篇讲到的Notifications窗口应用到实例中,我们可以仍旧使用NotificationControl文件,在其中对播放音乐Title进行绑定,即当音乐播放完毕后,即弹出消息提示播放下一首“XXX”音乐。效果如下图:

  根据上一篇介绍Notifications窗口的代码,我们简单进行修改,即可实现本篇实例需求:

 1          NotificationWindow notifyWindow  =   null ;
 2           private   void  ShowToast()
 3          {
 4              notifyWindow  =   new  NotificationWindow();
 5 
 6               if  (notifyWindow.Visibility  ==  Visibility.Visible)
 7                  notifyWindow.Close();
 8 
 9              NotificationControl myNotify  =   new  NotificationControl();
10              myNotify.DataContext  =  _playList[_nowPlaying];
11              notifyWindow.Width  =   300 ;
12              notifyWindow.Height  =   100 ;
13              notifyWindow.Content  =  myNotify;
14              notifyWindow.Show( 10000 );
15          }

  至此,一款基于Silverlight的Out of Browser模式的音乐播放器基本完成了。大家可以根据该实例添加更多自定义功能,例如添加互联网音乐播放功能,音乐搜索功能等,创建属于自己的Silverlight版酷我音乐盒。

  本篇源代码下载

目录
相关文章
|
6天前
|
人工智能 开发框架 量子技术
【专栏】.NET 技术:驱动创新的力量
【4月更文挑战第29天】.NET技术,作为微软的开发框架,以其跨平台、开源和语言多样性驱动软件创新。它在云计算、AI/ML、混合现实等领域发挥关键作用,通过Azure、ML.NET等工具促进新兴技术发展。未来,.NET将涉足量子计算、微服务和无服务器计算,持续拓宽软件开发边界,成为创新的重要推动力。掌握.NET技术,对于开发者而言,意味着握有开启创新的钥匙。
|
6天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
6天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
6天前
|
开发框架 Cloud Native 开发者
【专栏】剖析.NET 技术的核心竞争力
【4月更文挑战第29天】本文探讨了.NET框架在软件开发中的核心竞争力:1) .NET Core实现跨平台与云原生技术的融合,支持多操作系统和容器化;2) 提升性能和开发者生产力,采用JIT、AOT优化,提供C#新特性和Roslyn编译器平台;3) 支持现代化应用架构,包括微服务和容器化,内置安全机制;4) 丰富的生态系统和社区支持,拥有庞大的开发者社区和微软的持续投入。这些优势使.NET在竞争激烈的市场中保持领先地位。
|
6天前
|
开发框架 .NET 开发者
【专栏】领略.NET 技术的创新力量
【4月更文挑战第29天】.NET技术自ASP.NET起历经创新,现以.NET Core为核心,展现跨平台能力,提升性能与生产力,支持现代化应用架构。.NET Core使开发者能用同一代码库在不同操作系统上构建应用,扩展至移动和物联网领域。性能提升,C#新特性简化编程,Roslyn编译器优化代码。拥抱微服务、容器化,内置安全机制,支持OAuth等标准。未来.NET 6将引入更快性能、Hot Reload等功能,预示着.NET将持续引领软件开发潮流,为开发者创造更多机会。
|
6天前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
49 0
|
6天前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
23 0
|
6天前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
33 0
|
6天前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
6 0
|
6天前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
123 5