小总结:

所用技术:

01.C/S架构,数据存储在XML文件中

02.简单工厂模式

03.继承和多态

04.解析XML文档技术

05.深入剖析内存中数据的走向

06.TreeView控件的使用

核心:通过该项目,我们对业务流程有一个整体把控。对继承和多态有深入的了解

下面是类图:

主界面图:

核心思路:

   .首先在频道管理类ChannelManager中写一个加载所有频道方法LoadAllChannel;
 
       该方法作用读取FullChannels.xml文件,并且将读取到的内容赋值给ChannelBase          对象。关键的问题就转化成了如何创建一个ChannelBase对象。我们都知道ChannelBase本身是一个抽象类,无法创建实例。由此,我们想到可以通过其子类来创建对象。由于不同子类实例化需要多次new,我们单独写了一个工厂类(ChannelFafactory),来创建子类实例,但是该子类实例存储在父类变量中。赋值完成后,我们需要将频道对象添加到字典中。那么
 
LoadAllChannel方法结束后,字典中就有了XML文档中的数据。也就是我们实现了将
 
本地硬盘上的xml文件中的数据读取到了内存中的一个字典集合中。

  
.将集合中的数据绑定到TreeView中
将字典集合中的数据通过Foreach拆解,每循环一项,都创建一个TreeNode对象。
并且将集合中的属性赋值给节点对应的属性。然后将拼接处的节点添加到TreeView上
。这里需要注意的是,如何找到TreeView控件中的【所有电视台】这个节点,因为
我们需要在该节点上添加频道名称。代码如下:

 在对应的频道子类中书写Fetch方法,解析对应的频道xml文件,然后将xml文件中的数据读取到 public List<TvProgram>  TvList { get; set; }中。
    .将TvList中的数据绑定到DataGridView上
 
实现TreeView的右键菜单功能(能添加电台和删除电台)
  核心思路:
     .添加电台

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

通过Visible属性控制右键菜单的显示和隐藏:

 网络电视精灵后续思路
.点击TreeView上某个电视台节点后,显示该频道下所有的节目单,
将节目单内容填充到DataGridView控件中。
思路分析:既然TypeAChannel:ChannelBase对应的北京电视台,那么我们需要找到保存
北京电视台中所有节目的xml文件,然后接续该xml文件,每一个<TvProgram>
节点都是一个节目单对象。我只需要将解析出的内容加载到集合中。集合中就存储了
一系列TvProgram对象,我只需要将该集合绑定到DataGridView上就OK了。 DgvList.DataSource=list;

下面是本人写的一些代码:

      ChannelManager manager = new ChannelManager();
private void Form1_Load(object sender, EventArgs e)
{
lvTV.Visible = false;//让ListView控件隐藏
dgvProgList.AutoGenerateColumns = false;//不自动产生英文列
//1.加载我的电视台和所有电视台(TvChannel中的固定项)
TreeNode myNode = new TreeNode();
//点击该节点时,对应的图片改变
myNode.SelectedImageIndex = ;
myNode.Text = "我的电视台"; TreeNode allNode = new TreeNode();
allNode.SelectedImageIndex = ;
allNode.Text = "所有电视台"; //让节点和TreeView产生关系
tvChannel.Nodes.Add(myNode);
tvChannel.Nodes.Add(allNode); //2.接下来我们需要读取 xml文件 获取所有电视台下的子节点
//遍历集合中的每一项,然后拼接成一个TreeNode即可 manager.LoadAllChannel();
Dictionary<string, ChannelBase> fullChannel = manager.FullChannel;
foreach (ChannelBase channelBase in fullChannel.Values)
{
//每遍历一次,都是一个频道,每一次都要创建一个TreeNode节点
TreeNode tn = new TreeNode();
tn.Text = channelBase.ChannelName;
//Tag
tn.Tag = channelBase; //找到所有电台节点,在所有电台的基础上增加子节点
tvChannel.Nodes[].Nodes.Add(tn);
} //从txt文档将数据读取到集合中
if (File.Exists("files/Save.txt"))
{
manager.LoadFromTxt();
foreach (ChannelBase item in manager.MyChannelList.ChannelList)
{
//每一项item都是一个TreeNode对象
TreeNode tn=new TreeNode();
tn.Text = item.ChannelName;
tn.Tag = item; myNode.Nodes.Add(tn);
}
} imageIcons.Images[].Save("01.jpg");
imageIcons.Images[].Save("02.jpg"); //02.遍历集合拼接节点 } //选中TreeView中国某个节点后执行的事件
private void tvChannel_AfterSelect(object sender, TreeViewEventArgs e)
{
TreeNode tn = tvChannel.SelectedNode;//获取当前选中的节点对象
//点击某个节点(必须是子节点:Level==1)
if (tn!=null&&tn.Level==)
{
//发现是子节点,才获取到频道对象
ChannelBase channel = (ChannelBase) tn.Tag;
if (channel.TvList!=null)
{
channel.TvList.Clear();
}
channel.Fetch(); //然后将tvList集合绑定到DGV上
dgvProgList.DataSource = channel.TvList;
} }
//
private void tvChannel_MouseClick(object sender, MouseEventArgs e)
{
TreeNode node = tvChannel.SelectedNode;
if (node!=null&&node.Level==)//选中了电视台节点
{
if (node.Parent.Text=="我的电视台")
{
cmenuRight.Items[].Visible = false;
cmenuRight.Items[].Visible = true;
}
else
{
cmenuRight.Items[].Visible = true;
cmenuRight.Items[].Visible = false;
}
}
else
{
//如果选中节点为父节点,那么添加、删除菜单项都不显示
cmenuRight.Items[].Visible = false;
cmenuRight.Items[].Visible = false;
} }
//加入我的电台
private void tsmAddToFavor_Click(object sender, EventArgs e)
{
//如何将电台从所有电台加载到我的电台
//01.获取选中项
TreeNode tn = tvChannel.SelectedNode;
if (tn==null)
{
return;
}
//02.判断我的电台下是否已经存在你要加入的电台
foreach (TreeNode child in tvChannel.Nodes[].Nodes)
{
if (child.Text==tn.Text)
{
return;
}
}
//03.真正加入节点到我的电台下
//把当前选中的节点的Tag属性取出来,转换成ChannelBase
ChannelBase channel=(ChannelBase) tn.Tag;
//04.将channel对象添加到我的电台下成为我的电台的一个节点
TreeNode node=new TreeNode();
node.Text = channel.ChannelName;
node.Tag = channel;
tvChannel.Nodes[].Nodes.Add(node);
//04.将channel加入到集合中
manager.MyChannelList.ChannelList.Add(channel);
//05.如果集合在main 中,那么将集合中数据写入文本文件的时候比较麻烦
//所以我们将集合和SaveToTxt方法都写入了ChannelManager类
manager.SaveToTxt();
} //从我的电台中删除
private void TMenuItemDel_Click(object sender, EventArgs e)
{
//01.先获取我的电台下要删除的电台
//02.从Tv上移除
//03.从集合中移除
//04.SaveToTxt() }

//播放视频
private void tsmPlay_Click(object sender, EventArgs e)
{
string path= dgvProgList.SelectedRows[].Cells[].Value.ToString();
FrmPlay frm=new FrmPlay();
frm.mypath = path;
frm.Show();
frm.Play();
}

父类:

  /// <summary>
/// 频道基类
/// </summary>
public abstract class ChannelBase
{
//频道名称
public string ChannelName { get; set; }
//频道路径
public string Path { get; set; }
//频道类型
public string Type { get; set; }
//节目列表,该频道上的所有节目列表
public List<TvProgram> TvList { get; set; }
//获取频道列表:通过Fetch方法获取该频道拥有的所有节目列表
public abstract void Fetch(); } A频道
 //解析北京电视台中所有的节目单集合
public override void Fetch()
{
//既然我们已经拿到了所有的频道,只需要加载对应频道下节目就OK
//将硬盘中xml文件的数据读取到了泛型集合中(内存中)
XmlDocument doc=new XmlDocument();
doc.Load(Path);
if (TvList==null)
{
TvList=new List<TvProgram>();
}
XmlElement root = doc.DocumentElement;
foreach (XmlNode item in root.ChildNodes)
{
if (item.Name == "tvProgramTable")
{
//
foreach (XmlNode tn in item.ChildNodes)
{
TvProgram program=new TvProgram();
program.PlayTime=Convert.ToDateTime(tn["playTime"].InnerText);
program.Name = tn["programName"].InnerText;
program.ShiDuan = tn["meridien"].InnerText;
program.Path = tn["path"].InnerText; TvList.Add(program);
}
}
}
}

B频道

  public class TypeBChannel:ChannelBase
{
public override void Fetch()
{
XmlDocument doc = new XmlDocument();
doc.Load(Path);
if (TvList == null)
{
TvList = new List<TvProgram>();
}
XmlElement root = doc.DocumentElement;
foreach (XmlNode item in root.ChildNodes)
{
foreach (XmlNode tn in item.ChildNodes)
{
TvProgram program = new TvProgram();
program.PlayTime = Convert.ToDateTime(tn["playTime"].InnerText);
program.Name = tn["name"].InnerText; program.Path = tn["path"].InnerText; TvList.Add(program);
}
}

传递类

 public class ChannelManager
{
private const string channelPath = "files/Fullchannels.xml";
public ChannelManager()
{
this.fullChannel = new Dictionary<string, ChannelBase>();
this.myChannelList=new SavingInfo();
}
//所有频道列表(string:名称 ChannelBase:频道父类)
private Dictionary<string, ChannelBase> fullChannel;
public Dictionary<string, ChannelBase> FullChannel
{
get { return fullChannel; }
set { fullChannel = value; }
} public SavingInfo MyChannelList
{
get { return myChannelList; }
set { myChannelList = value; }
} //保存我的电台
private SavingInfo myChannelList;
//加载所有频道
public void LoadAllChannel()
{
XmlDocument doc=new XmlDocument();
doc.Load(channelPath);
//获取根节点
XmlElement root=doc.DocumentElement; foreach (XmlNode item in root.ChildNodes)
{
//加上注释!@@@@
ChannelBase channel= ChannelFactory.CreateChannel(item["channelType"].InnerText);
foreach (XmlNode xmlNode in item.ChildNodes)
{ switch (xmlNode.Name)
{
case "tvChannel":
channel.ChannelName= xmlNode.InnerText;
break;
case "path":
channel.Path = xmlNode.InnerText;
break;
case "channelType":
channel.Type = xmlNode.InnerText;
break;
}
}
fullChannel.Add(channel.ChannelName,channel);
} }

  //简单工厂
public static class ChannelFactory
{
public static ChannelBase CreateChannel(string type)
{
ChannelBase channel=null;
switch (type)
{
case "TypeA":
channel = new TypeAChannel();
break;
case "TypeB":
channel = new TypeBChannel();
break;
}
return channel;
}
}


1  //节目类
public class TvProgram
{
//播出时间
public DateTime PlayTime{ get; set; }
// 早间档,午间档,晚间档
public string ShiDuan { get; set; }
public string Name { get; set; }
//视频路径
public string Path { get; set; }
}
 public class SavingInfo
{
//构造函数
public SavingInfo()
{
this.ChannelList=new List<ChannelBase>();
} //我的收藏:定义了一个泛型集合,保存我的电台下所有的频道
private List<ChannelBase> channelList; public List<ChannelBase> ChannelList
{
get
{
return channelList;
}
set { channelList = value; }
}
}

完结待续。。。。。。。。。。。。。。。。

网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档,视频项目的更多相关文章

  1. 结合实例分析简单工厂模式&工厂方法模式&抽象工厂模式的区别

    之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个 ...

  2. Java解析XML文档(简单实例)——dom解析xml

      一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object ...

  3. 简单工厂模式&工厂方法模式&抽象工厂模式的区别

    之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个 ...

  4. C# 设计模式(1)——简单工厂模式、工厂模式、抽象工厂模式

    1.前言 上一篇写了设计模式原则有助于我们开发程序的时候能写出高质量的代码(牵一发而不动全身),这个系列还是做个笔记温习一下各种设计模式,下面就看看简单工厂模式.工厂模式.抽象工厂模式. 2.简单工厂 ...

  5. C#设计模式系列:简单工厂模式(Simple Factory)

    1. 简单工厂模式简介 1.1 定义 简单工厂模式定义一个Factory类,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类. 简单工厂模式只需要一个Factory类. 简单工厂模式又 ...

  6. C++设计模式——简单工厂模式

    简单工厂模式(Simple Factory Pattern) 介绍:简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些.因为它至少不是Gof23种设计模式之一.但它在实际的编程中经常被用 ...

  7. PHP中“简单工厂模式”实例讲解

    原创文章,转载请注明出处:http://www.cnblogs.com/hongfei/archive/2012/07/07/2580776.html 简单工厂模式:①抽象基类:类中定义抽象一些方法, ...

  8. Design Patterns (简单工厂模式)

    文章很长很精彩,如是初学请耐心观看.(大神请绕道!) 简单工厂模式: 1.创建型模式 2.简单工厂模式概述 3.简单工厂模式的结构与实现 4.简单工厂模式的应用实例 5.创建对象与使用对象 6.简单工 ...

  9. Simple Factory 简单工厂模式(静态工厂)

    基本概念: 1) Simple Factory模式属于创建型模式, 2) 简单工厂模式是由一个工厂(注意是一个!)对象决定创建出哪一种产品类的实例(例如你到肯德基说你要鸡腿,要薯条,要饮料还是,,,这 ...

随机推荐

  1. [mobile开发碎碎念]手机页面上显示PDF文件

    demo:http://mozilla.github.io/pdf.js/web/viewer.html 项目地址:https://github.com/mozilla/pdf.js <scri ...

  2. JavaWeb前端:JQuery

    Jquery基本概念 什么是Jquery Jquery是一个开源的,集成了Javascript,CSS,DOM,AJAX的前端框架:它诞生于2006年,最初是为了简化JavaScript开发而产生的, ...

  3. visual studio 工具的使用

    1,快捷键 a, ctrl+e ,ctrl+c 快速注释  ctrl+e ,ctrl+u 取消注释 b,ctrl+k,ctrl+d 快速格式化. 2,开发相关 a,在Microsoft Visual ...

  4. UI测试 错题分析

    从服务器端获取的json对象,可以直接访问对象中的属性 该属性的作用就是C text属性显示节点文本,state属性默认为open 看错行  不能用 ' ' 包裹 state:节点状态,'open' ...

  5. jquery笔记之属性选择器 查找以某种条件开头的页面元素

    jquery笔记之属性选择器 查找以某种条件开头的页面元素 转载:http://www.blogbus.com/amyqiong-logs/78340326.html $("div[id]& ...

  6. Codeforces Round #374 (Div. 2) D. Maxim and Array

    传送门 分析:其实没什么好分析的.统计一下负数个数.如果负数个数是偶数的话,就要尽量增加负数或者减少负数.是奇数的话就努力增大每个数的绝对值.用一个优先队列搞一下就行了. 我感觉这道题的细节极为多,非 ...

  7. IT求职中,笔试、面试的算法准备

    PS:此文章为转载,源地址:http://www.newsmth.net/nForum/#!article/CoderInterview/849     作者应该是在美国进行的笔试面试,感觉面试的的公 ...

  8. Ecshop 后台增加一个左侧列表菜单menu菜单的方法

    Ecshop 后台增加一个左侧列表菜单menu菜单需要修改三个文件:/admin/includes/inc_menu.php/admin/includes/inc_priv.php/languages ...

  9. innodb 存储引擎特性

    使用独立表空间后,系统表空间存储什么内容呢?   1.innodb 数据字典信息   和存储引擎相关.   frm 是服务器的数据字典和存储引擎无关. 2. undo 回滚段.   可以单独存储.   ...

  10. AntiXSS v4.0中Sanitizer.GetSafeHtmlFragment等方法将部分汉字编码为乱码的解决方案

    AntiXSS v4.0中Sanitizer.GetSafeHtmlFragment等方法将部分汉字编码为乱码的解决方案 以下代码为asp.net环境下,c#语言编写的解决方案.数据用Dictiona ...