WPF一步一脚印系列(1):万事起头难

时间:2022-04-22
本文章向大家介绍WPF一步一脚印系列(1):万事起头难,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  一直从事Asp.Net的开发,而C/S的开发方面简直是一片空白,于是从上星期开始就痛下决心开始学习WPF。我采取的策略是网上看基础资料+做简单的demo练习+网上查资料。从csdn上下了个比较不错的基础讲解文档,花了几天时间终于把它看完,算是有个基本了解吧,今天开始写些小练习。

  这个系列主要是用来记录自己学习WPF的心路历程,以实例为主配合原理和注意点的说明,有纰漏之处请大家多多指正!!^_^

实例1——倒计算器                                                                                                                                                                                   

最终效果:

Window1.xaml:

 1 <Window x:Class="CountingLeader.Window1"
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     Title="Window1" Height="300" Width="300">
 5     <Grid>
 6         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
 7             <StackPanel.Resources>
 8                 <Style TargetType="TextBlock">
 9                     <Setter Property="FontSize" Value="50"></Setter>
10                 </Style>
11             </StackPanel.Resources>
12             <TextBlock x:Name="tbkHour" Text="00"></TextBlock>
13             <TextBlock Text=":"></TextBlock>
14             <TextBlock x:Name="tbkMinute" Text="10"></TextBlock>
15             <TextBlock Text=":"></TextBlock>
16             <TextBlock x:Name="tbkSecond" Text="45"></TextBlock>
17         </StackPanel>
18     </Grid>
19 </Window>

Window1.xaml.cs:

 1 namespace CountingLeader
 2 {
 3     /// <summary>
 4 /// Window1.xaml 的交互逻辑
 5 /// </summary>
 6     public partial class Window1 : Window
 7     {
 8         private CountingLeaderManager clm = null;
 9 
10         public Window1()
11         {
12             InitializeComponent();
13 
14             this.Loaded += new RoutedEventHandler(Window_OnLoaded);
15             clm = new CountingLeaderManager();
16         }
17 
18         public void Window_OnLoaded(object sender, RoutedEventArgs e)
19         {
20             clm.TotalCount = Convert.ToInt32(this.tbkHour.Text) * 3600 +
21                 Convert.ToInt32(this.tbkMinute.Text) * 60 +
22                 Convert.ToInt32(this.tbkSecond.Text);
23 
24             DispatcherTimer timer = new DispatcherTimer();
25             timer.Interval = new TimeSpan(0,0,1);
26             timer.Tick += (ss, ee) =>
27                 {
28                     if (clm.CanReduce())
29                     {
30                         clm.Reduce();
31                         this.tbkHour.Text = clm.GetHour();
32                         this.tbkMinute.Text = clm.GetMinute();
33                         this.tbkSecond.Text = clm.GetSecond();
34                     }
35                     else
36                         timer.Stop();
37                 };
38             timer.Start();
39         }
40     }
41 }

CountingLeader.cs:

 1 namespace CountingLeader
 2 {
 3     public class CountingLeaderManager
 4     {
 5         public int TotalCount { get; set; }
 6 
 7         public bool CanReduce()
 8         {
 9             if (TotalCount == 0)
10                 return false;
11             else
12                 return true;
13         }
14 
15         public int Reduce()
16         {
17             return --TotalCount;
18         }
19 
20         public string GetHour()
21         {
22             return GetCount(() => TotalCount / 3600 );
23         }
24 
25         public string GetMinute()
26         {
27             return GetCount(() => TotalCount % 3600 / 60);
28         }
29 
30         public string GetSecond()
31         {
32             return GetCount(() => TotalCount % 60);
33         }
34 
35         private string GetCount(Func<int> func)
36         {
37             string result = string.Empty;
38             int resultInt = func();
39             if (resultInt <= 9)
40                 result = "0" + resultInt;
41             else
42                 result = resultInt.ToString();
43 
44             return result;
45         }
46     }
47 }

wf时期的有三种计时器供大家使用:System.Threading.Timer、System.Timers.Timer和System.Windows.Forms.Timer,如果计时器用在UI上那么就使用System.Timers.Timer,因为它由UI线程实现;如果实现与UI无关的操作可以用System.Threading.Timer,它是从系统的线程池中取线程实现计时器的功能,但因不是用UI线程实现而无法操作UI上的控件;而System.Timers.Timer是由服务器实现,具体有待研究。

而该练习使用的计时器是System.Windows.Threading.DispatcherTimer,.net frameword 3.0后提供,感觉像是wf中的System.Windows.Forms.Timer。

注意:由UI线程实现的计时器会阻塞UI的交互操作。

1 timer.Tick += (ss, ee) =>
2     {
3          System.Threading.Thread.Sleep(100000);
4     };

将Window1.xaml.cs文件中的timer.Tick部分修改为上述代码后,明显看到计时器跟UI交互操作使用的同一个线程。

实例2:简易多媒体播放器                                                                                                                                  

最终效果:

Window1.xaml:

 1 <Window x:Class="VideoPlayer.Window1"
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     Title="Window1" Height="300" Width="300">
 5     <StackPanel>
 6         <Border Background="Gray">
 7             <Border.BorderBrush>
 8                 <SolidColorBrush Color="Silver"></SolidColorBrush>
 9             </Border.BorderBrush>
10             <MediaElement x:Name="me" LoadedBehavior="Manual" MinHeight="200"
11                           Volume="{Binding ElementName=volumeSlider,Path=Value}"></MediaElement>
12         </Border>
13         <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
14             <StackPanel.Resources>
15                 <Style TargetType="Button">
16                     <Setter Property="Background">
17                         <Setter.Value>
18                             <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
19                                 <LinearGradientBrush.GradientStops>
20                                     <GradientStopCollection>
21                                         <GradientStop Color="White" Offset="0.1"></GradientStop>
22                                         <GradientStop Color="#232323" Offset="1"></GradientStop>
23                                     </GradientStopCollection>
24                                 </LinearGradientBrush.GradientStops>
25                             </LinearGradientBrush>
26                         </Setter.Value>
27                     </Setter>
28                     <Setter Property="Margin" Value="2"></Setter>
29                     <Setter Property="FontStyle" Value="Italic"></Setter>
30                     <Style.Triggers>
31                         <Trigger Property="IsMouseOver" Value="true">
32                             <Setter Property="Foreground" Value="Gold"></Setter>
33                         </Trigger>
34                         <Trigger Property="IsEnabled" Value="false">
35                             <Setter Property="Foreground" Value="Gray"></Setter>
36                         </Trigger>
37                     </Style.Triggers>
38                 </Style>
39             </StackPanel.Resources>
40             <Button x:Name="btnOpenFile" Content="Open File" Click="btnOpenFile_Click"></Button>
41             <Button x:Name="btnPlayOrPause" Content="Play" Click="btnPlayOrPause_Click" IsEnabled="False"></Button>
42             <Button x:Name="btnStop" Content="Stop" Click="btnStop_Click" IsEnabled="False"></Button>
43             <Button x:Name="btnBack" Content="Back" Click="btnBack_Click" IsEnabled="False"></Button>
44             <Button x:Name="btnForward" Content="Forward" Click="btnForward_Click" IsEnabled="False"></Button>
45         </StackPanel>
46         <StackPanel Orientation="Horizontal">
47             <TextBlock Text="Volume:"></TextBlock>
48             <Slider x:Name="volumeSlider" Maximum="1" Minimum="0" Value="0.5" Width="200" ></Slider>
49         </StackPanel>
50     </StackPanel>
51 </Window>

说明:

1.MediaElement的Volume(声音)是依赖属性可以使用Slider作为数据源将Slider的Value值绑定到MediaElement;

2.Style中Trigger用来设置按钮的不可用、鼠标在上面时样式的变化。

Window1.xaml.cs:

 1 namespace VideoPlayer
 2 {
 3     /// <summary>
 4 /// Window1.xaml 的交互逻辑
 5 /// </summary>
 6     public partial class Window1 : Window
 7     {
 8         private bool IsPlaying = false;
 9 
10         public Window1()
11         {
12             InitializeComponent();
13         }
14 
15         private void btnOpenFile_Click(object sender, RoutedEventArgs e)
16         {
17             OpenFileDialog ofd = new OpenFileDialog();
18             ofd.Filter = "mp3文件(*.mp3)|*.mp3|wmv文件(*.wmv)|*.wmv|avi文件(*.avi)|*.avi";
19             if(ofd.ShowDialog()==System.Windows.Forms.DialogResult.OK)
20             {
21                 this.me.Source = new Uri(ofd.FileName, UriKind.Absolute);
22                 this.btnForward.IsEnabled = true;
23                 this.btnBack.IsEnabled = true;
24                 this.btnPlayOrPause.IsEnabled = true;
25                 this.btnStop.IsEnabled = true;
26             }
27         }
28 
29         private void btnForward_Click(object sender, RoutedEventArgs e)
30         {
31             this.me.Position += TimeSpan.FromSeconds(10);            
32         }
33 
34         private void btnBack_Click(object sender, RoutedEventArgs e)
35         {
36             this.me.Position -= TimeSpan.FromSeconds(10);
37         }
38 
39         private void btnPlayOrPause_Click(object sender, RoutedEventArgs e)
40         {
41             if (IsPlaying)
42             {
43                 this.me.Pause();
44                 (sender as System.Windows.Controls.Button).Content = "Play";
45                 IsPlaying = false;
46             }
47             else
48             {
49                 this.me.Play();
50                 (sender as System.Windows.Controls.Button).Content = "Pause";
51                 IsPlaying = true;
52             }
53         }
54 
55         private void btnStop_Click(object sender, RoutedEventArgs e)
56         {
57             this.btnPlayOrPause.Content = "Play";
58             this.me.Stop();
59             IsPlaying = false;
60         }
61     }
62 }

说明:

1.这里使用了System.Windows.Forms.OpenFileDialog控件,如果针对Window7开发可以使用WindowsAPICodePack;

以上是今天做的练习,十分简单最适合像我这样的初学者了,一步一个脚印坚持不懈!!