热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用BabySmash学习WPF用另一双眼睛将事物推向更高水平

NOTE:Ifyouhaventreadthefirstpostinthisseries,Iwouldencourageyoudotothatfirst,orcheckoutthe

NOTE: If you haven't read the first post in this series, I would encourage you do to that first, or check out the BabySmash category. Also check out http://windowsclient.net/ for more developer info on WPF.

注意:如果您还没有阅读本系列第一篇文章,我建议您先阅读该文章,或者查看BabySmash类别 另请访问http://windowsclient.net/以获取有关WPF的更多开发人员信息。

BACKGROUND: This is one of a series of posts on learning WPF. I wrote an application for my 2 year old using WPF, but as I'm a Win32-minded programmer, my working app is full of Win32-isms. It's not a good example of a WPF application even though it uses the technology. I'm calling on community (that's you, Dear Reader) to blog about your solutions to different (horrible) selections of my code. You can get the code http://www.codeplex.com/babysmash. Post your solutions on your blog, in the comments, or in the Issue Tracker and we'll all learn WPF together. Pick a single line, a section, or subsystem or the whole app!

背景:这是有关学习WPF的一系列文章之一。 我使用WPF为2岁的孩子编写了一个应用程序,但是由于我是位Win32程序员,所以我的工作应用程序充满了Win32-ism。 即使它使用WPF技术,也不是WPF应用程序的好例子。 我正在呼吁社区(即您,亲爱的读者)在博客中介绍您针对我的代码的不同(糟糕)选择的解决方案。 您可以获取代码http://www.codeplex.com/babysmash 。 将您的解决方案发布到您的博客,评论或问题跟踪器中,我们将一起学习WPF。 选择一条线,一个部分,子系统或整个应用程序!

BabySmash has a little mini-heirarchy of "Figures" that represent the Shapes on the screen, along with a little additional information like the name of the Figure ("square", "circle") as well as an English word for the color. I intend to internationalize it at some point.

BabySmash在屏幕上具有代表图形的“图形”微型层次结构,以及一些其他信息,例如图形名称(“正方形”,“圆圈”)以及英语的颜色。 我打算将其国际化。

Figure has been pretty simple so far and doesn't really do anything:

到目前为止,Figure很简单,实际上并没有做任何事情:

public abstract class Figure
{
private UIElement shape;
private readonly string name;
private readonly string color;

protected Figure(Brush fill, string name)
{
this.color = Utils.BrushToString(fill);
this.name = name;
}

public UIElement Shape
{
get { return shape; }
protected set { shape = value; }
}

public string Name { get { return name; } }
public string Color { get { return color; } }
}

Derived Shapes are mostly declarative, and very repetitive:

派生形状主要是声明性的,并且非常重复:

public class SquareFigure : Figure
{
public SquareFigure(Brush fill)
: base(fill, "square")
{
Shape = new Rectangle()
{
Fill = fill,
Height = 380,
Width = 380,
StrokeThickness = 5,
Stroke = Brushes.Black,
};
}
}

public class StarFigure : Figure
{
public StarFigure(Brush fill)
: base(fill, "star")
{
Shape = new Star()
{
NumberOfPoints = 5,
Height = 400,
Width = 400,
Fill = fill,
StrokeThickness = 5,
Stroke = Brushes.Black,
};
}
}

Last post, we removed a bunch of the Style related stuff and put it into XAML markup as a shared Style application resource we could use all over. This makes things DRYer (Don't Repeat Yourself) but still something doesn't smell right.

上一篇文章,我们删除了一堆与Style相关的内容,并将其作为XAML标记作为共享的Style应用程序资源,我们可以全部使用。 这会使事情变干(不要重复自己),但仍然闻不到正确的气味。

I still have to grab the Style and pass the Fill along into the Shape property, and I do it for EVERY Shape. Meh. It's the same four lines over and over again.

我仍然必须获取Style并将Fill传递到Shape属性中,并且对每个Shape都要这样做。 嗯一遍又一遍是相同的四行。

public class SquareFigure : Figure
{
public SquareFigure(Brush fill)
: base(fill, "square")
{
Shape s = new Rectangle();
s.Style = Application.Current.Resources["square"] as Style;
s.Fill = fill;
Shape = s;
}
}

Ripe for refactoring I say. Note the call to base() in the Constructor. You'd be surprised how many people either don't know about base() or who knew and forgot. ;)

我说重构的时机已经成熟。 注意在构造函数中对base()的调用。 您会惊讶于有多少人对base()不了解,或者谁知道并忘记了。 ;)

Oddly, I was already passing Fill into the constructor, and then passing it up the hierarchy to the abstract base class Figure without thinking. This is very common when you slap code together then finally take a breath and LOOK at it. Ever more common when you have someone who isn't "into" the code just look over your shoulder and say "um, what's THAT?" You really can't overestimate how useful another set of eyes are. I did a quick SharedView with Jason this afternoon and his fresh eyes sped up my refactoring considerably.

奇怪的是,我已经将Fill传递给构造函数,然后不加考虑地将其沿层次结构传递给抽象基类Figure。 当您将代码拍到一起然后最后屏住呼吸并看一下时,这是很常见的。 当您遇到一个不“喜欢”代码的人时,通常会越过您的肩膀说“嗯,那是什么?”,这种情况越来越普遍。 您真的不能高估另一只眼睛的用处。 我今天下午和Jason做了一个快速的SharedView ,他新鲜的眼睛大大加快了我的重构速度。

public abstract class Figure
{
private readonly string name;
private readonly string color;

protected Figure(Brush fill, string name, Shape s)
{
this.color = Utils.BrushToString(fill);
this.name = name;
this.Shape = s;
s.Fill = fill;
s.Style = Application.Current.Resources[Name] as Style;
}

public UIElement Shape { get; protected set; }

public string Name { get { return name; } }
public string Color { get { return color; } }
}

Here we moved everything that was repeated (shared) up into the base class. The Shape property used the C# 3.0 property syntax that let us remove a field (it's generated now). Notice the use of the protected keyword on the setter.

在这里,我们将重复(共享)的所有内容移至基类中。 Shape属性使用C#3.0属性语法,该语法使我们可以删除字段(该字段现在已生成)。 注意在setter上使用protected关键字。

The only thing that "smells" bad about this for me is the call to Application.Current.Resources. This is the moral equivalent to HttpContext.Current as it's saying "reach out into the heavens that you ought not know about and pull a rabbit out of a hat" or, in this case, a resource out of Application.Resources. However, as far as I can tell, this is a minor sin, and a common one, unless I want to start passing all these bits of information around my hierarchy while trying to obey the Law of Demeter, which I'm arguably already breaking.

对此我唯一“闻”到不好的是对Application.Current.Resources的调用。 这在道德上等同于HttpContext.Current,因为它的意思是“伸出您不应该知道的天堂,将兔子从帽子里拉出来”,或者在这种情况下,将资源从Application.Resources中移除。 但是,据我所知,这是一个轻微的错误,也是一个普遍的错误,除非我想开始遵循遵从Demeter的定律来开始在我的等级体系中传递所有这些信息,但我可能已经打破了。

Regardless, suddenly my library of Figures becomes much simpler. Of course, adding new ones will be even simpler now. For example:

无论如何,突然之间,我的数字图书馆变得更加简单。 当然,现在添加新的将更加简单。 例如:

public class RectangleFigure : Figure
{
public RectangleFigure(Brush fill)
: base(fill, "rectangle", new Rectangle()){}
}

public class CircleFigure : Figure
{
public CircleFigure(Brush fill)
: base(fill, "circle", new Ellipse()){}
}

public class TriangleFigure : Figure
{
public TriangleFigure(Brush fill)
: base(fill, "triangle", new Polygon()){}
}

public class StarFigure : Figure
{
public StarFigure(Brush fill)
: base(fill, "star", new Star()){}
}

In the next post I'll refactor the factory that makes these figures into something that allows me to sleep at night. ;)

在下一篇文章中,我将重构使这些数字变成可以让我晚上睡觉的东西的工厂。 ;)

BabySmash,BabySmash , WPF,WPF ,Refactoring重构

翻译自: https://www.hanselman.com/blog/learning-wpf-with-babysmash-pushing-things-up-a-level-with-another-set-of-eyes




推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
author-avatar
rvr4845591
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有