小总结:
所用技术:
01.C/S架构,数据存储在XML文件中
02.简单工厂模式
03.继承和多态
04.解析XML文档技术
05.深入剖析内存中数据的走向
06.TreeView控件的使用
核心:通过该项目,我们对业务流程有一个整体把控。对继承和多态有深入的了解
下面是类图:


主界面图:

核心思路:
1 1.首先在频道管理类ChannelManager中写一个加载所有频道方法LoadAllChannel;
2
3 该方法作用读取FullChannels.xml文件,并且将读取到的内容赋值给ChannelBase 对象。关键的问题就转化成了如何创建一个ChannelBase对象。我们都知道ChannelBase本身是一个抽象类,无法创建实例。由此,我们想到可以通过其子类来创建对象。由于不同子类实例化需要多次new,我们单独写了一个工厂类(ChannelFafactory),来创建子类实例,但是该子类实例存储在父类变量中。赋值完成后,我们需要将频道对象添加到字典中。那么
4
5 LoadAllChannel方法结束后,字典中就有了XML文档中的数据。也就是我们实现了将
6
7 本地硬盘上的xml文件中的数据读取到了内存中的一个字典集合中。
9
10 2.将集合中的数据绑定到TreeView中
11 将字典集合中的数据通过Foreach拆解,每循环一项,都创建一个TreeNode对象。
12 并且将集合中的属性赋值给节点对应的属性。然后将拼接处的节点添加到TreeView上
13 。这里需要注意的是,如何找到TreeView控件中的【所有电视台】这个节点,因为
14 我们需要在该节点上添加频道名称。代码如下:
1 在对应的频道子类中书写Fetch方法,解析对应的频道xml文件,然后将xml文件中的数据读取到 public List<TvProgram> TvList { get; set; }中。
2 2.将TvList中的数据绑定到DataGridView上
3
4 实现TreeView的右键菜单功能(能添加电台和删除电台)
5 核心思路:
6 1.添加电台


1 其实我们在做的事情就是先获取所有电台的某一个电台(北京电视台),然后通过
2 Tag属性拿到该电台对应的属性,将拆解出来的属性赋值给我的电台下的某一个
3 节点,由于节点不存在,所以我们要构造出一个节点。然后赋值,赋值完成后,我们就将构造出来的 节点添加到我的电台下就OK。
4
5 当然,上面的操作仅仅是界面上新增电台的一个假象。程序再次运行时,我们添加的电台并没有保存。所以我们要将选中的电台添加到我的电台(由于我喜欢的电台可能有多个,所以我们定义了一个集合。)集合中。因为我们大家都知道集合中的数据时存储在内存中的,所以我们要向程序下次运行时,显示出我们添加的电台,那么就必须将集合中的数据永久保存。当然我们知道,永久保存数据的方法有很多,在这里我们采取的是使用txt文件的方式,所以我们书写了一个方法来帮我们完成这项工作,sw.WriteLine(“End”)主要为了方便后面对文本文件的读取
通过Visible属性控制右键菜单的显示和隐藏:

1 网络电视精灵后续思路
2 1.点击TreeView上某个电视台节点后,显示该频道下所有的节目单,
3 将节目单内容填充到DataGridView控件中。
4 思路分析:既然TypeAChannel:ChannelBase对应的北京电视台,那么我们需要找到保存
5 北京电视台中所有节目的xml文件,然后接续该xml文件,每一个<TvProgram>
6 节点都是一个节目单对象。我只需要将解析出的内容加载到集合中。集合中就存储了
7 一系列TvProgram对象,我只需要将该集合绑定到DataGridView上就OK了。
8
9 DgvList.DataSource=list;
下面是本人写的一些代码:
:
1 ChannelManager manager = new ChannelManager();
2 private void Form1_Load(object sender, EventArgs e)
3 {
4 lvTV.Visible = false;//让ListView控件隐藏
5 dgvProgList.AutoGenerateColumns = false;//不自动产生英文列
6 //1.加载我的电视台和所有电视台(TvChannel中的固定项)
7 TreeNode myNode = new TreeNode();
8 //点击该节点时,对应的图片改变
9 myNode.SelectedImageIndex = 1;
10 myNode.Text = '我的电视台';
11
12 TreeNode allNode = new TreeNode();
13 allNode.SelectedImageIndex = 1;
14 allNode.Text = '所有电视台';
15
16 //让节点和TreeView产生关系
17 tvChannel.Nodes.Add(myNode);
18 tvChannel.Nodes.Add(allNode);
19
20 //2.接下来我们需要读取 xml文件 获取所有电视台下的子节点
21 //遍历集合中的每一项,然后拼接成一个TreeNode即可
22
23 manager.LoadAllChannel();
24 Dictionary<string, ChannelBase> fullChannel = manager.FullChannel;
25 foreach (ChannelBase channelBase in fullChannel.Values)
26 {
27 //每遍历一次,都是一个频道,每一次都要创建一个TreeNode节点
28 TreeNode tn = new TreeNode();
29 tn.Text = channelBase.ChannelName;
30 //Tag
31 tn.Tag = channelBase;
32
33 //找到所有电台节点,在所有电台的基础上增加子节点
34 tvChannel.Nodes[1].Nodes.Add(tn);
35 }
36
37
38
39 //从txt文档将数据读取到集合中
40 if (File.Exists('files/Save.txt'))
41 {
42 manager.LoadFromTxt();
43 foreach (ChannelBase item in manager.MyChannelList.ChannelList)
44 {
45 //每一项item都是一个TreeNode对象
46 TreeNode tn=new TreeNode();
47 tn.Text = item.ChannelName;
48 tn.Tag = item;
49
50 myNode.Nodes.Add(tn);
51 }
52 }
53
54 imageIcons.Images[0].Save('01.jpg');
55 imageIcons.Images[1].Save('02.jpg');
56
57 //02.遍历集合拼接节点
58
59 }
60
61 //选中TreeView中国某个节点后执行的事件
62 private void tvChannel_AfterSelect(object sender, TreeViewEventArgs e)
63 {
64 TreeNode tn = tvChannel.SelectedNode;//获取当前选中的节点对象
65 //点击某个节点(必须是子节点:Level==1)
66 if (tn!=null&&tn.Level==1)
67 {
68 //发现是子节点,才获取到频道对象
69 ChannelBase channel = (ChannelBase) tn.Tag;
70 if (channel.TvList!=null)
71 {
72 channel.TvList.Clear();
73 }
74 channel.Fetch();
75
76 //然后将tvList集合绑定到DGV上
77 dgvProgList.DataSource = channel.TvList;
78 }
79
80 }
81 //
82 private void tvChannel_MouseClick(object sender, MouseEventArgs e)
83 {
84 TreeNode node = tvChannel.SelectedNode;
85 if (node!=null&&node.Level==1)//选中了电视台节点
86 {
87 if (node.Parent.Text=='我的电视台')
88 {
89 cmenuRight.Items[0].Visible = false;
90 cmenuRight.Items[1].Visible = true;
91 }
92 else
93 {
94 cmenuRight.Items[0].Visible = true;
95 cmenuRight.Items[1].Visible = false;
96 }
97 }
98 else
99 {
100 //如果选中节点为父节点,那么添加、删除菜单项都不显示
101 cmenuRight.Items[0].Visible = false;
102 cmenuRight.Items[1].Visible = false;
103 }
104
105 }
106 //加入我的电台
107 private void tsmAddToFavor_Click(object sender, EventArgs e)
108 {
109 //如何将电台从所有电台加载到我的电台
110 //01.获取选中项
111 TreeNode tn = tvChannel.SelectedNode;
112 if (tn==null)
113 {
114 return;
115 }
116 //02.判断我的电台下是否已经存在你要加入的电台
117 foreach (TreeNode child in tvChannel.Nodes[0].Nodes)
118 {
119 if (child.Text==tn.Text)
120 {
121 return;
122 }
123 }
124 //03.真正加入节点到我的电台下
125 //把当前选中的节点的Tag属性取出来,转换成ChannelBase
126 ChannelBase channel=(ChannelBase) tn.Tag;
127 //04.将channel对象添加到我的电台下成为我的电台的一个节点
128 TreeNode node=new TreeNode();
129 node.Text = channel.ChannelName;
130 node.Tag = channel;
131 tvChannel.Nodes[0].Nodes.Add(node);
132 //04.将channel加入到集合中
133 manager.MyChannelList.ChannelList.Add(channel);
134 //05.如果集合在main 中,那么将集合中数据写入文本文件的时候比较麻烦
135 //所以我们将集合和SaveToTxt方法都写入了ChannelManager类
136 manager.SaveToTxt();
137 }
138
139 //从我的电台中删除
140 private void TMenuItemDel_Click(object sender, EventArgs e)
141 {
142 //01.先获取我的电台下要删除的电台
143 //02.从Tv上移除
144 //03.从集合中移除
145 //04.SaveToTxt()
146
147 }
148 //播放视频 149 private void tsmPlay_Click(object sender, EventArgs e) 150 { 151 string path= dgvProgList.SelectedRows[0].Cells[3].Value.ToString(); 152 FrmPlay frm=new FrmPlay(); 153 frm.mypath = path; 154 frm.Show(); 155 frm.Play(); 156 }
父类:
1 /// <summary>
2 /// 频道基类
3 /// </summary>
4 public abstract class ChannelBase
5 {
6 //频道名称
7 public string ChannelName { get; set; }
8 //频道路径
9 public string Path { get; set; }
10 //频道类型
11 public string Type { get; set; }
12 //节目列表,该频道上的所有节目列表
13 public List<TvProgram> TvList { get; set; }
14 //获取频道列表:通过Fetch方法获取该频道拥有的所有节目列表
15 public abstract void Fetch();
16
17 }
A频道
1 //解析北京电视台中所有的节目单集合
2 public override void Fetch()
3 {
4 //既然我们已经拿到了所有的频道,只需要加载对应频道下节目就OK
5 //将硬盘中xml文件的数据读取到了泛型集合中(内存中)
6 XmlDocument doc=new XmlDocument();
7 doc.Load(Path);
8 if (TvList==null)
9 {
10 TvList=new List<TvProgram>();
11 }
12 XmlElement root = doc.DocumentElement;
13 foreach (XmlNode item in root.ChildNodes)
14 {
15 if (item.Name == 'tvProgramTable')
16 {
17 //
18 foreach (XmlNode tn in item.ChildNodes)
19 {
20 TvProgram program=new TvProgram();
21 program.PlayTime=Convert.ToDateTime(tn['playTime'].InnerText);
22 program.Name = tn['programName'].InnerText;
23 program.ShiDuan = tn['meridien'].InnerText;
24 program.Path = tn['path'].InnerText;
25
26 TvList.Add(program);
27 }
28 }
29 }
30 }
B频道
1 public class TypeBChannel:ChannelBase
2 {
3 public override void Fetch()
4 {
5 XmlDocument doc = new XmlDocument();
6 doc.Load(Path);
7 if (TvList == null)
8 {
9 TvList = new List<TvProgram>();
10 }
11 XmlElement root = doc.DocumentElement;
12 foreach (XmlNode item in root.ChildNodes)
13 {
14 foreach (XmlNode tn in item.ChildNodes)
15 {
16 TvProgram program = new TvProgram();
17 program.PlayTime = Convert.ToDateTime(tn['playTime'].InnerText);
18 program.Name = tn['name'].InnerText;
19
20 program.Path = tn['path'].InnerText;
21
22 TvList.Add(program);
23 }
24 }
25
传递类
1 public class ChannelManager
2 {
3 private const string channelPath = 'files/Fullchannels.xml';
4 public ChannelManager()
5 {
6 this.fullChannel = new Dictionary<string, ChannelBase>();
7 this.myChannelList=new SavingInfo();
8 }
9 //所有频道列表(string:名称 ChannelBase:频道父类)
10 private Dictionary<string, ChannelBase> fullChannel;
11 public Dictionary<string, ChannelBase> FullChannel
12 {
13 get { return fullChannel; }
14 set { fullChannel = value; }
15 }
16
17 public SavingInfo MyChannelList
18 {
19 get { return myChannelList; }
20 set { myChannelList = value; }
21 }
22
23 //保存我的电台
24 private SavingInfo myChannelList;
25 //加载所有频道
26 public void LoadAllChannel()
27 {
28 XmlDocument doc=new XmlDocument();
29 doc.Load(channelPath);
30 //获取根节点
31 XmlElement root=doc.DocumentElement;
32
33 foreach (XmlNode item in root.ChildNodes)
34 {
35 //加上注释!@@@@
36 ChannelBase channel= ChannelFactory.CreateChannel(item['channelType'].InnerText);
37 foreach (XmlNode xmlNode in item.ChildNodes)
38 {
39
40 switch (xmlNode.Name)
41 {
42 case 'tvChannel':
43 channel.ChannelName= xmlNode.InnerText;
44 break;
45 case 'path':
46 channel.Path = xmlNode.InnerText;
47 break;
48 case 'channelType':
49 channel.Type = xmlNode.InnerText;
50 break;
51 }
52 }
53 fullChannel.Add(channel.ChannelName,channel);
54 }
55
56 }
1 //简单工厂
2 public static class ChannelFactory
3 {
4 public static ChannelBase CreateChannel(string type)
5 {
6 ChannelBase channel=null;
7 switch (type)
8 {
9 case 'TypeA':
10 channel = new TypeAChannel();
11 break;
12 case 'TypeB':
13 channel = new TypeBChannel();
14 break;
15 }
16 return channel;
17 }
18 }
1 //节目类
2 public class TvProgram
3 {
4 //播出时间
5 public DateTime PlayTime{ get; set; }
6 // 早间档,午间档,晚间档
7 public string ShiDuan { get; set; }
8 public string Name { get; set; }
9 //视频路径
10 public string Path { get; set; }
11 }
1 public class SavingInfo
2 {
3 //构造函数
4 public SavingInfo()
5 {
6 this.ChannelList=new List<ChannelBase>();
7 }
8
9 //我的收藏:定义了一个泛型集合,保存我的电台下所有的频道
10 private List<ChannelBase> channelList;
11
12 public List<ChannelBase> ChannelList
13 {
14 get
15 {
16 return channelList;
17 }
18 set { channelList = value; }
19 }
20 }
完结待续。。。。。。。。。。。。。。。。