<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8207014087154934703</id><updated>2024-10-03T22:32:51.880+08:00</updated><category term="vue.js"/><category term="Android"/><title type='text'>Jain&#39;s 學習之路</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>95</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-3366181718866673891</id><published>2018-01-04T14:26:00.001+08:00</published><updated>2018-01-04T14:26:01.014+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>Android – Activity / Service 的生命狀態</title><content type='html'>&lt;p&gt;之前在學習 android app 開發所做的筆記，在此記錄一下.&lt;p&gt;&lt;font size=&quot;3&quot;&gt;每個Activity有四個生命狀態：&lt;/font&gt;&lt;ul&gt;&lt;li&gt;Active／Running：當一個Activity在螢幕的最上層時(堆疊的最頂端)，它就是屬於Active或Running的狀態&lt;/li&gt;&lt;br&gt;&lt;li&gt;Paused：如果一個Activity失去焦點(focus)但還看得到它的畫面，那失去焦點的這個Activity則處在Paused的狀態。失去焦點的Activity它還是完全活著的，並沒有消失。(活著的意思是指Activity自已本身所有的狀態及資料都還是存在的也跟視窗管理程式window manager保持連繫著)像這種Paused的Activity，可能在系統的記憶體不足的時後，被系統自動移除掉&lt;/li&gt;&lt;br&gt;&lt;li&gt;Stopped：如果一個Activity被其它的Activity完全的遮住時，這個被遮的Activity處於stop的狀態，它仍然保有全部的狀態及資料，但因為它已不再被使用者看見，所以它的畫面是被隱藏起來的(畫面不需要更新)。當系統記憶體不足時，這種Stop狀態的Activity是最先被系統考慮拿來釋放記憶體的&lt;/li&gt;&lt;br&gt;&lt;li&gt;Finished： 當一個Activity處於Pause或Stop的狀態時，系統可以要求Activity結束(Finish)或直接移除(Kill)它。當它需要再度呈現在使用者面前時，它必需要能完整的重新啟動及回復先前的狀態&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;font size=&quot;3&quot;&gt;每個Service有兩種生命狀態：&lt;/font&gt;&lt;ul&gt;&lt;li&gt;Started：當一個組件(例如：一個Activity)呼叫startService()的時候，Service就進入Started狀態。一個Service一旦被啟動，就會一直在背景運行，就算啟動的組件被關閉還是繼續運行。&lt;br&gt;&lt;br&gt;一般而言，一個被啟動的Service只會執行一個功能，執行完畢後並不會回傳結果給啟動的組件。例如：某個Service會透過網路下載或上傳一個檔案。當傳輸工作結束，該Service應該自動關閉。&lt;/li&gt;&lt;br&gt;&lt;li&gt;Bound：當一個組件(例如：一個Activity)呼叫bindService()的時候，Service就進入Bound狀態。&lt;br&gt;處於Bound狀態的Service，和呼叫的組件的關係類似client-server介面，讓組件和Service互相溝通、傳送與接收信息，甚至可以透過IPC跨process交換信息。&lt;br&gt;&lt;br&gt;一個處於Bound狀態的Service，只要有一個對應的組件就會運行。多個組件可以同時bind到同一個Service，但當所有的組件unbind的話，該Service也會關閉。&lt;/li&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/3366181718866673891/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2018/01/android-activity-service.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3366181718866673891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3366181718866673891'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2018/01/android-activity-service.html' title='Android – Activity / Service 的生命狀態'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-1424304247871952573</id><published>2018-01-02T09:10:00.001+08:00</published><updated>2018-01-02T09:14:38.454+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js – vuex 狀態管理</title><content type='html'>&lt;p&gt;入門前最後需了解的一個 library ，vuex 這集中式存儲管理所有組件的資料狀態. 當一個 app 在做非同步處理時，我們希望可以有個 Loading 的畫面可以讓使用者知道 app 是有在 work 的，一般都是把這個功能做在主頁面上，其它的子頁面都是呼叫主頁面的 method 來 enable/disable，這個時候就是 vuex 上場的時機了.&lt;/p&gt;&lt;p&gt;Vuex 這個部份網路上已有很多的介紹了，請自行善用 Google 大神吧.&lt;/p&gt;&lt;p&gt;Vuex 觀念&lt;/p&gt;&lt;p&gt;&lt;img width=&quot;544&quot; height=&quot;368&quot; alt=&quot;vuex 官網流程圖&quot; src=&quot;https://vuex.vuejs.org/zh-cn/images/flow.png&quot;&gt;&lt;/p&gt;&lt;p&gt;首先我們依照官網的步驟安裝 vuex &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZD0qfjDrKd8fS6EQ8B4wOepjGNZufg_P8CBVWQGq-Kj-IIz7i8EHmAbvdGOsc4rucwyczEOpjMbDHC2KgW-7JovxFShvCyJFcY3FQxD1UYESLJg0rN0RrOkTyNd3owhgaMuHRNP_YGfU/s1600-h/image3&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;101&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF91LAFxrzORbsO_hVZPFLxXAQ1j2g67iRu4jG8XdtpUs0XjEfFX1CcleuiZgco-IMpRg-gk7gjhSngLUJp-hfNrgx_8KriyRhRCSNoHZdIyGNt28ZLoeaZoEK04XKcsm1D6WZSdKQ1GM//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;在來在 src 下新增一個 store 的資料夾，裡面分別有 5 隻 js 檔案&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6IGQTH26m_fGoRXbQmhwm_eVvU_apTItB3VDrR3HyxXqO3CwGoqguQULYZZkfeg4nZ4uG5jFYIWDBddQe-8MMjfpOKipESGkuEQZyuhnsgJtlDASST0ArugKnfIP9TQDA9dT-y2o1uiQ/s1600-h/image7&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;435&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcj-hjImewaROBJpm57J2msDD2lumCv5BNpaf0hZ__AjgQUdRKxtsg5aI-YCC0Ethj0YfmQCLsWUH5xwUrbdgElJ_WlyUxPBuv2-7jzdQdhSG2HBwkKIT2p6wq3Vdd7cJ9CYnRTs1fFEg//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;分別在各個 js 檔案中撰寫相對應的程式碼.&lt;/p&gt;&lt;p&gt;mutations_types.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkdkbYIKvsnPmOTRTU9SG130d65UwyTmJD8Vq-cOjrjOTnlVQDEDug-B29BssV0tIB1Q-FdSixAccC8aXStpARcJqfCdXtRtai8BqNH0eJHyG13F1L7mxJLO9AJvUM_5p3vXTZEu-EcZ8/s1600-h/image11&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;183&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMhuLDrjJ87YJ821tWgcSqm4CVukr1cstOeE8XO3pz2JhPJrGUmdQCtQ5ew22KM2S2XjjDnzuUDXBLMt-2y4eUMrUJFNBF2xrwHH_akO4UXm7Csk3_4FF35pcf3aBw5GzR3Nj9DM41_HE//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;mutations.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikHTx26r7LBsZA4gNLRh3FoywK5AFYXyFs2b-p1E4-srqJ54iXhrQKqoEAHkRZbpxSySLfq2-OlR0spUiwztkmmkP7GJwcYJ6shFtWzLpeNNZySY0QSoZj5OISX1Q-Q5d-HbvNXiiNR9M/s1600-h/image15&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;260&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGZ8Fy7VokVrKRfJb-RMxKBnJBeJ_cLXt7cujHVYiANkK6F4_ZIZqdCim__eWj32TgRFTbwSESEMUa6hwxo1mYiD-QiDjl50cFbx8_vCp9nyAfCtX_o3iIb8yIwjVYzdKEMMAVZlSWB-4//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;getters.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSOgg034Iq-DcVGSKRtsSm_uPN6Jp-JNlOnavYLyCSCXcrvpyUeZpMAWzEnIA9CYMCb8a4WvUzwMZPukTfOIt5IhCzSSTXt4RiCGgQ9MZAM5NKRYvAlYmX67ymvNhXFyc65lyihAPm9o0/s1600-h/image19&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;231&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHPkgZPq_y7nampKfs2GWOBdu4f6XEabgWyaJo13oEYvrnKvc5Pcjxu4hTQAEq-iL-aIGX8MyH_2K9SvQw3c25JCOsxwsfHm9dLwz97Fit-gdpbo0MzmZvUZ6TUfXFJB-lAJhWhAslm3w//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;actions.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-Y3-VlPvlyRuekYGCnqR0RI-YavBb8iPsJW0uFisc-FCy2wameJf90WY4fYR3ttOYH1qsQYtLECAI-89ptJyIlqgwMIM_7wk41BkJ3r04BDmRD9d7-IIWdzwiRsX4vi4Hho4jXM65IXU/s1600-h/image23&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;228&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglmUfKjRET9csCAjN6ytzT0lXcwBX7x0SaAj82uVXhJ1Ln3TUmixur7FAPL1B-A5oGIL6_LP8VvG1cGi7XuztTgBFbgfPqVPNev4j765UNCc3i3L9qdhgAZT4zHfCzTGefSxok_0rHewg//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;index.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYiEb0EQRYnXvJKFgMuLcdwzYaSrUcUEZPobstbbYtLoAX4IitU8mgCQti1PTYs1reKoP6d5QX_FRfxt1vEWWaJJkajCfTCKlkNWPGMbYOV7tWgUKZxa7oRm4Xk4bnouuKlDEsUO-Tk-g/s1600-h/image27&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;378&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibAQwcY9T4omE6f7fORBWhkuhrXKOHBUu4L6XZo1SyExCf8elzGHXGjKjxH9otAdMv5S7VMK_u-TQs0sO5xE5P45RF5sKu8lQZDS5zwDLlZ7CxS3RSNyyfeNXGEqjOua4EzD9EiDBRSM0//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;按著在 main.js 中引用 store 中的 js 檔案.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijRqNSQbNalzB95CqFr6LeOftzgLp7_YHUQvKs1LEClTBV5E8p3k6YVRJ_a1ZYHnczh8kDGEKku9vXFcqvUs9_GDiv6ax8knKpCfyNv8TkUX9REzQAECBuC28YR_frJsFjXixtVNcDj-Y/s1600-h/image31&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;389&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ugdHoZ6bhdFUKIbVGz3u_Dk18_dwVQDX4ATouXwqkqZXLUv-maAhLabwWO5mAQBEl2RxrOECeZ5xt9O7fLwgQ4MI1vRmPJlAoc3S2Wd7D3qUZmGQfTgw5P0FGrTEE_vfsrLtPHQ6Iso//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接著我們修改 App.vue 這個 main page&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHRCqzD73Qe6e4UpVNnUBvn9bcPn9i6ptcaXS8WH5f2UalVN91ZoRbGdS8aInXmNY5Gr2yovCe4z9s9AIWwVXRpZTn13lBtmHJo1P16VzmOF7UdM2XYES-rus4NzESPH89-r2Jf2vfQYk/s1600-h/image%255B4%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;403&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl46m3pbhmNg35HQsmii_2wCoK8o-nnfmCbr05bii_yypF5rKhWImLAcj3B46vJBDXxR4EoFQpITdHsNL0RnROvjdUIshXWnD_a4scZ78xmsNqb9oZLa1rzyEfk0YpqXJWEzJY7gf28OI//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接著修改 component&amp;nbsp; 的程式碼&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4L8aGO0XVrp1CxdDTmbm2FiSqx8MmfWzoWbzEzWVQ_ELSFyic7c9FzBamtDv8KL3W_RIKXyUjfXMocRspLULqv7L0d05hVgkF2EIOBBcOlUrZTXKUfQhhorL5VmrCzHSP2j4ek69Kf4/s1600-h/image%255B8%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;351&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIG7E83KP5GvoPHZgVy2iy6UzWsENHU_4boiKjwDdLUZfU36VwWs7wmxe31MmYL70UPIS8YEa_p-EeRmTzq3NDk3kVcFh-vrBpwMTAFYo5SQBLZr1AR-6gtVJC1Rw9XYTCPPaLDebo8kA//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;如此就可以在切換頁面時出現 Loading 的效果.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimVJoLF6DDnFzMnwHkQ8oEqf1N2znmHV02On5v38Ld4B6bX8Z5H54bVwbFvL8VXkwoQWMiFaf2DMovfcE-m-KdYI1MBldj9MwOSzTChd_j_8QZFKUIe8OJMLLgBmBDcoybEyCwFBgcbK0/s1600-h/image%255B12%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;315&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg27Cg7fPhSlej7k_6HAfegLh1EGtsBrhZ8VjE82-zpFjNUokw1mUpvcg4oOF6E8rSOf0-hFvaHBDnmipZdpyCTcmDKWOBuq8MF1JOS9GWJ2D0niiRWyknqA2LPrXZLIkbh_-gNSqDurHY//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;PS : 這個時候在 run 時會有 error 的問題， “ …mapActions “ 這個 method 無法 compile，需安裝Stage 2 preset 來 bypass 這個錯誤訊息.相關的訊息如下:&lt;/p&gt;&lt;p&gt;&lt;a title=&quot;https://forum-archive.vuejs.org/topic/5023/i-am-getting-an-error-when-i-use-mapgetters-on-vuex-2-0&quot; href=&quot;https://forum-archive.vuejs.org/topic/5023/i-am-getting-an-error-when-i-use-mapgetters-on-vuex-2-0&quot;&gt;https://forum-archive.vuejs.org/topic/5023/i-am-getting-an-error-when-i-use-mapgetters-on-vuex-2-0&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a title=&quot;https://babeljs.io/docs/plugins/preset-stage-2/&quot; href=&quot;https://babeljs.io/docs/plugins/preset-stage-2/&quot;&gt;https://babeljs.io/docs/plugins/preset-stage-2/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;.babelrc file &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRp3hyphenhyphenZMQ6c5cDhnBsJUHdiok_IKK3u0FT24gXUQqiNJ1ZgK1dqH2GFDjnxOG3ZIu0utYp0TsZANEUKikMuzmds4EFP9MKHjwHjpGLqlSRLWuOWfMb4ekXlCuL3i3sOA5oEBllz_IJ42s/s1600-h/image%255B4%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;305&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVJH5jfHlLRnIv0f9chMHDu3VyBbGet28tbTEFUSK-J5wud7S6JsXxpr0Z4gM9WjagKuy1O4HUib4CjwwOh9zgD9xjzjh9tzrHJdHjK3XHH3nSkkhOCQhkwcJxYDhztV6iPz8aAfZ-C5Y//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/1424304247871952573/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2018/01/vuejs-vuex.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1424304247871952573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1424304247871952573'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2018/01/vuejs-vuex.html' title='Vue.js – vuex 狀態管理'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF91LAFxrzORbsO_hVZPFLxXAQ1j2g67iRu4jG8XdtpUs0XjEfFX1CcleuiZgco-IMpRg-gk7gjhSngLUJp-hfNrgx_8KriyRhRCSNoHZdIyGNt28ZLoeaZoEK04XKcsm1D6WZSdKQ1GM/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-5513589346796918289</id><published>2017-12-29T19:15:00.000+08:00</published><updated>2017-12-29T19:15:10.696+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js - 基礎介紹教學</title><content type='html'>今年的 iT邦幫忙鐵人賽中剛好就有位鐵人利用了 30 天的時間，天天一篇文章從頭到尾來介紹 vue.js 的基礎教學，這真的是太佛心來了，在此記錄一下也方便以後有需要的時候可以直接取得相關的訊息.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10184834&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 01 - Vue Introduction &amp;amp; 鐵人賽說明&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10184919&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 02 - 使用 Vue-cli 安裝 vue 和 webpack 環境與相關套件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185065&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 03 - Hello World &amp;amp; 雙向綁定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185164&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 04 - 使用 vue-router 建構 Single Page Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185258&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 05 - 攝氏轉換華氏工具 - I (computed)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185326&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 06 - 攝氏轉換華氏工具 - II (v-if, v-show, methods)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185457&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 07 - component - I (元件拆解，合併，靜態資料引用)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185521&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 08 - component - II (v-for 小幫手解決重複元件)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185618&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 09 - component - III (slot 在元件上鑽洞)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185686&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 10 - 什麼是 vuex?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185784&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 11 - 計數器 - I (vuex 職權與流程說明)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185810&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 12 - 計數器 - II (action, mutation 傳遞資料)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10185957&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 13 - 經典 todo list - I (create, read)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186037&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 14 - 經典 todo list - II (改變狀態與 delete)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186121&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 15 - 經典 todo list - III (update)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186219&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 16 - 自訂按鈕 custom checkbox ($emit, $on)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186481&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 17 - 覺得 store 有點亂，動手拆成 modules 吧！&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186713&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 18 - 開發小技巧&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10186866&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 19 - Shopping cart - I (v-bind, :class, 數據驅動)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187013&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 20 - Shopping cart - II (購物車，推薦商品加購)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187049&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 21 - Open Data - I (元件的生命週期、透過 ajax 取得資料)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187193&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 22 - Open Data - II (高雄市 opendata、加上過場 loading 效果)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187319&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 23 - Open Data - III (搜尋條件、select option、v-else、watch)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187542&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 24 - Login - I (action Promise、rouetr change)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187631&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 25 - Login - II (router auth、rouetr beforeEach)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187723&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 26 - 使用 SASS 管理 CSS - webpack sass-loader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187812&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 27 - 進階路由顯示 - multiples views、nested routes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10187909&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 28 - custom Directive (toggle password)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10188048&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 29 - custom Filter (currency、Letter Grade、GPA、lowercase)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ithelp.ithome.com.tw/articles/10188139&quot; target=&quot;_blank&quot;&gt;vue &amp;amp; vuex 30 - 網站系統國際化 - 多語系(i18n)與持續學習相關資源&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/5513589346796918289/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs_29.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/5513589346796918289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/5513589346796918289'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs_29.html' title='Vue.js - 基礎介紹教學'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-6119393023522244162</id><published>2017-12-26T13:49:00.001+08:00</published><updated>2017-12-29T19:15:31.432+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js – Vue Router 的介紹</title><content type='html'>&lt;p&gt;在看到 Router 時也是第一次接觸到 SPA (Single Page Application) 這個名詞 . 簡單的說就是把 Web Application&amp;nbsp; 變成是 Desktop Application 來開發. 基本上傳統的 Web Site 採取多頁式 ( Multi-Page ) 做法，而是如何把 UI 從 Server-side 移到 Client-side，資料的部份整合 REST API ，做到真正的前後端分離.&lt;/p&gt;&lt;p&gt;&lt;img width=&quot;544&quot; height=&quot;244&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCu5iy7ahD2nkoQOLra8TSyrhQ0l8UhHUbywJ4CNH3au9cKYmAhym6asgXmSfnDNTGBVYtVxMs_pAyzeXUdU6_ZBFBby8mHjmInPDcMabihyWrZeVA7mZuvxWSqRCgfpVlYV7NJYVoBvI/s1600/SPAs.png&quot;&gt;&lt;/p&gt;&lt;p&gt;Router 的工作就是為了把 Server 的路由變成是 Client 端，頁面的切換全部交給 Client 來處理.&lt;/p&gt;&lt;p&gt;vue 在 init project 時會詢問是否要使用&amp;nbsp; vue router library，在建立 project 時幫你加入 router 的功能.這個檔案就是在配置路由來取代 hyperlink 回 Server 的部份.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNWoqAfqNqH2B90r97L4rF5taQrxxHwBId9M6y8XeCB3gefH4bZUjddPpMDDPwQ61ZDM8A4vM7UuNP-EkokbL7uI1kRVKyjYyz3Z57ta-XhoMaYGwXOwscPIu1KJlgW_vgD0QkKeeGauY/s1600-h/image3&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;423&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0eDpRmSRVddKMphQxh8Y-xwu0EQyaHQlVrFA1o2B363oGRRKG65VJGSXyKegze1fQlFpchMOeKlg4ZjywXPAj6AJBLdFFTYW3NqJ2_rfF8mJ0ArxgrS9CkELITWFkbUNCnQOoiEektxE//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggETV97xWvAIN16SHHpG2eGwTfURBXNZCvARg2EZblQs2_tUCCFhdhEl9i-BUK0eAIvg2_rjIVurhpkm0QftY4-33qU1qcQyz-K8_0P0cujoTrmV6-k_52hb2HOo4CVwd40T_yMwNc3rU/s1600-h/image7&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;339&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBcr39ZNMsYfY0jW6_KL3oO2JILBDjeB_WRbeNMGobXyXSRAiCeLi7wNKOSWdxSic1MHEAmqYz5HgJSfipIoFv0G4y6kPJwGEzO5Y0LIpaGlQKGFiRo8NZ3of5NJcrWEWDH9KrloEE_ow//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;試著修改路由的配置及加入 element-ui 的 NavMenu 的 library 做過簡單的範例.&lt;/p&gt;&lt;p&gt;首先在其 components folder 中加入 SayHi.vue，做其簡單的輸出.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuL-CrFMlIsBETQbJAeWzzRMl9IGSmoML01en5I__yZfUpV4-ACgRFhN6h1heTtziZTf2ZNWBv7NtdZhGbpLCgP976ZkjHVJkk_HpInOi_dveXUQB-DnZOwWD-EmUhlxuupW32VypFlaw/s1600-h/image11&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;355&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid_5ma3EljEu70i2pWtM9dNiUFSkThsAZUWbt5ZUfg7wo_tWVm1eVgjV4KOkNhqZdXyVXrbFmAnuEzXV18wkfwJlEVwC9arGq3Eq_9P11UrdYPELN-PBvxlB2bQjWwke4gbwZALeHUlkM//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;再來修改 router folder 中的 index.js，定義 Path 所要載入的 component 組件( UI ) 為何.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcNPA5aLEDlGyjf3N1ncjrlycgaNFr3eDfVBGaY9GG57wYvMpPzchjBTS4M5CQ103Vr9QNAH8HC3z3ogf2SnL6dvrHaiNKnYkkbfQaNmmS8nDuBEqn2oVshLGZZhwR6sPpmHZG33GPLVE/s1600-h/image15&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;595&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEHKfpW8Zv-nAaAo10VYJiR9OdRcA1v9KFz_unD908nX_QVS1XTOMQMyXp-KiHsGB0TDEtyljOY1Kxv5-54F1PWwdZScdhLzC9Qw4WIsYRwciaxUQf7NbCTBAGHwHQ_c15WsCWnyI4g-c//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最後修改 App.vue，加入 router-view 這個 Tag，來定義所要顯示的區域 .&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEircrjTWSjmGtIpOiXLgHwsjic_ajmALI98wmyRFozy3RMBWh-B7WKUXC4f3gqDK4nyjuxBFmnl3RwINt5oNX2Hfvfvo_YcE3VpOGZKzzvXu_wpL0tJMuu95B6q3S9invAQUxXUb0R6fvE/s1600-h/image19&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;324&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUNviomed86FhbdgNBZ0Vfr3k4L5r3YlJY917iwbnuCJKdFZyPDD4OfNtSjt7ofk6H4_Qb15yYYLYgnlCN1kuKwqK0zDiUzO31gV8pgPPuIN6M_IG08A1B7Mhac6Pt4vigR6tU2BzExWg//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最基本的&amp;nbsp; router 功能就完成. 來看一下最後的畫面. &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSc0d6Q_Cqdwkuc3zT0FpnG_kA7Eom67bqMKnX5E4t8o_P7cKNsvlPDVSzJrN0riNjUf6_Y5jb7udVRJGiGeYr7x7oy9P3VJcqfDP3JoygxflwhiXmMaU_bJJ8LSwgFWR3DVU3Mao00Ls/s1600-h/image26&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;333&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6ULmNkca5X_3FSnesorpoCkKJBd-lyIAmrl-hFW_MTTgOnJ6NBuJE1LDjUmZXgNYBhneJlC9NX0v3Y-ZMiq6g0dl2oku-SONwvC0EeBTzVCdMKQmXJI4IocyMZd_iujncUjWpNrkKEDE//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSAmP8r48QPvrvb6UBkcI-__yNVK4y3jz-LZK7n581ii-V-FSbUa75o8GD_kzkpqy9I3QQPibfTgbADOfm2dj5tW8y8zlwWadrgZWVNhR3zPbnu6HCxDMdw_oewsx1NySGZiSl6cSya7w/s1600-h/image27&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;278&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaNeigN24e9_l0K4FyCmGS9IuRhFJ4nE_nH9IJH_OcKjjmF8RQskB-EYLofaBH4IsTJN2cSnhIRDUWsW8l3haAvu252uDAHdgeaGPHlGy6DJSXQNCsqPWoCqPiu3vaGIz6FrvB_H4aU3Y//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/6119393023522244162/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-vue-router.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6119393023522244162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6119393023522244162'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-vue-router.html' title='Vue.js – Vue Router 的介紹'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCu5iy7ahD2nkoQOLra8TSyrhQ0l8UhHUbywJ4CNH3au9cKYmAhym6asgXmSfnDNTGBVYtVxMs_pAyzeXUdU6_ZBFBby8mHjmInPDcMabihyWrZeVA7mZuvxWSqRCgfpVlYV7NJYVoBvI/s72-c/SPAs.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-671177899967446298</id><published>2017-12-25T13:58:00.001+08:00</published><updated>2017-12-29T19:15:31.478+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js - 使用 babel-plugin-component 減少 File Size</title><content type='html'>&lt;p&gt;雖然已成功使用 element-ui 來開發，但其 build 出來的 file size 還真的有夠大. 再來就依官網所說的使用 babel-plugin-component 來減少 file size . 使用 npm 來按裝 babel-plugin-component.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8gjK1P94hovVtWH8FK2pCeaB5SUXdaTfGWCk7BVrzEyFW3NvSo36jUV_z87zk_pJZu4-BUIuGJvMZPfiSigYJCBTijxCBTXMb4FzcgPI5ZhtKjxpuC2acYT6ptuHXz3SEZCOGjxonqO4/s1600-h/image%255B9%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;74&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUf-L36huja6mYBMW_5Hy_XjHHkdDMR_I4HfDooxWPaAVBvFqTlCWDCs5yIL668-AgbQOKCYlJzYPMi8Yp7wyNJK9iXCl-gK84HdVqrjODK3wiEHNDiasCGceY0-eZUsGGcbex6CaRvG0//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;再來修改&amp;nbsp; main.js&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxsujx-xBqRlMYLWcdRgTTp6Ctb0K0yxBhMj5yRXIgoZ_zQ5I-16UcGAU_MrYGftFD8GFCiQvgVzHqrMATcA2AzqJ5K2CNQ7shkjazn-lFjY_Gq7TapS73-a6smhvGX4UKwqVqgSKznp8/s1600-h/image%255B13%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;267&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVF5GbQ1X-xeoiiI2yniRc3j8MaN_3oWZJD_EscOLrQ7OK0RaSct7DHntcFIAGe5ckw70EHdW0IVIO0Yj0yJRGSoxaLVwHa_SDvSLbO1CmY7qOMeO4PK3AwcQwLNQKzdNZyCVYt9QMt-k//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;重點是 .babelrc 這個 file，我依官網的來修改在執行時會有錯誤訊息，可能是版本新舊的關係，故做點小修改才沒有錯誤訊息.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLCSndIV7NZw0VUcmnOGGGr0i9Vh-5dOTlLASgRivofXm99DtvsxRxnF1WwW3UZ4bzVlTINfxlB4qU_JEiWs5Fg_4OQvrtXH240j5e5rkJGhiD4UGJuXuZu8pcyKfSZtLJpG3a3e33dtg/s1600-h/image%255B17%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;274&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdsITMsrHs27DlY9ctUAwpzRbJ1uXbjJdYT9zhL76AZ9lqKTijuuB7qVuZsXU-88rMln6A9sU4S2QYmJT0I23KFkd6ccFAqTS49WfYs7NDoQ5oKm3jrJgLSXtXXx1EF4cw6vuqSHeUu6Q//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;比較一下使用 babel-plugin-component 前後 build 出來的 file size 二者的差異，檔案的大小對瀏覽器載入的時間是正相關啊．&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4iOx2WJ5YvNa1ssvCtpFbkvDlpcNOXH4elnyc3skm7R0YnglFH3bqSVRX5ytlLGbl9Sw91YYHM7EAZv_BDai7ugwb20Wxcf0REPKokp1aEtyEK1DpbhpGiz7DfervSzd8At1NTqEDviQ/s1600-h/image%255B18%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;315&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcrR2W6iGwRFOlP9A0yJmrOrWJ_yuOnzKtfvHu2vMEU02v-U9HKKDhW0yMQcHd5MWfabXu7VdKRqqk5tQEBQsryRpqMkl74VqmZv_cqOiUr7_e5YyMIZyOi7YcH1IWTVVhxReVkdh6VVc//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixL_-jIJF9PmTSCOIc7etMydRx35R9uKhHgQ8D_wwvUaFQhOe7U0u4Hz5TqS_1NG5Qvnu70neEA1dTrRoXh4zioc8ZqPtFZ8bzw6EYRcHUtDcgYFlKI-N6Sz4CNxGrR1pp3X_l_eMfO9o/s1600-h/image%255B19%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;294&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjt7_T_0e4pY4jINBifLirYzSs6_4Fs1UBh9xw6fmSQyE_gaM5c2PIUH640X_XxPqEWtcpgMmzrtAoKD4cVkbVagwDYAnh6nfoA6CGJP6ZigmmFd290UA-9Ra_89tfMfZek0Fbl6GrpqHA//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/671177899967446298/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-babel-plugin-component-file-size.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/671177899967446298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/671177899967446298'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-babel-plugin-component-file-size.html' title='Vue.js - 使用 babel-plugin-component 減少 File Size'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUf-L36huja6mYBMW_5Hy_XjHHkdDMR_I4HfDooxWPaAVBvFqTlCWDCs5yIL668-AgbQOKCYlJzYPMi8Yp7wyNJK9iXCl-gK84HdVqrjODK3wiEHNDiasCGceY0-eZUsGGcbex6CaRvG0/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-4119803614588237986</id><published>2017-12-25T11:54:00.001+08:00</published><updated>2017-12-29T19:15:31.295+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js - 加入 Element Component</title><content type='html'>&lt;p&gt;工欲善其事，必先利其器，awesome-vue ( &lt;a title=&quot;https://github.com/vuejs/awesome-vue&quot; href=&quot;https://github.com/vuejs/awesome-vue&quot;&gt;https://github.com/vuejs/awesome-vue&lt;/a&gt; )幫我們收集了很多的關於 Vue.js 的 resource ，有好的材料當然也要配上好的料理才行. 在選取技術最重要的不外乎 resource 的多寡，當有問題時可以取得解答和大量的 component 可以加速你的開發是我列入選取的重要選取條件之一.&lt;/p&gt;&lt;p&gt;Vue.js 的 UI Framework 的部份我選擇使用 Element 來當做我之後開發的 library.最快上手不外乎是官方文件 ( &lt;a title=&quot;http://element.eleme.io/#/zh-CN&quot; href=&quot;http://element.eleme.io/#/zh-CN&quot;&gt;http://element.eleme.io/#/zh-CN&lt;/a&gt; ) .&lt;/p&gt;&lt;p&gt;接著之前的範例，加入其 Element library ，一樣透過 npm 來安裝 element-ui&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipPS1zV3hdmxRh-gewUAXRCrZtjAbCPiT4ycjeCG4RKUDN0bkHH2hhP-QNUSDev4Zwk68dBCPdAOt68ZSv6VGZzk7qNSSS5gWkg-N2sEYNFj27x974E2tAbktU0U6auicGKyX_dOH_1AI/s1600-h/image%255B3%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;79&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32uR_eGxzFkHQxWOFC4YjtIVsxx_ICKeLWJwIop6uIJLZX1w0Djbk1fu7u3IDaF-M-rS27vTb_oQL9AeWjxXHzfkNHoCqQgmRVeJcqCrtsf9-AeChfqmYVqpUa07z165YZBmmTa3Kk0w//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接著在 main.js 中宣告使用 element-ui &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjlRSwfbWpJyRwqtdGvaLqkzu8LQ6hEJ7_CYsVZaTrzILjBnOG2a_VQcZZoixRB116q5kX9zNdpEKEqD6ew-jst9oUvTUl-15AXHpEXSd6_inwtGn2oRH9LaE1lq3ZHC5GXjlc2kzwE7Y/s1600-h/image%255B7%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;437&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMGuLpfs1sVBk-KttCW2C276d2SajPxj8mIrqnCivyNvlERGu5zWBLKo6sZQAwODAA7JxwCscddI55lzBBRCg2MSaymiURHrQ1bL2EUIqX_zk2uwMlXKMJPnlFWktieymqJS2H49dBp9k//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最後修改一下 App.vue 來測試是否可正常執行.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-3gby3wOsOwPy-CjmEWLvLYRIXpfP8ttB8BzN8gPVNdzRWlMNkVIOwvllGs3qYstWKmTZ67od_Ysea_OSke-PnXGd_-dHFEUqoWyZKOTQLO-_moW9gQUc5ZdW7gYBRAymEyQqDv9bfQA/s1600-h/image%255B11%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;224&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgau3kKLJrwABYI7XCjYuA_q_H1vJuOXgysUlDfJ8nAEJ5hMabtauoum76skK_CWDaUmyXg9srEtViXPX1qSOGBJ-AYKP1z4uIuYWAngxjS2CTqshIxdqRQ5OnUa_W5AOrqr0PHBQAA7cI//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;執行畫面如下，可以看到&amp;nbsp; Button 可正常的顯示.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjdFbQTYJ8vNVTDQLmqquvORsGGwZZQogjKARkDsZ0HzPK0axQhJuxz3EXwy4NF00xgdP8woQsZnNwCX1EFnz-XxCfa5lMfz5_tB5r0TC6DGc0Jjq-RY-KV23FtiGm9axY2RGqCjZe5E/s1600-h/image%255B15%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;362&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGeCIQTtnPYq9IgcY1t1o7KpVadv693JidImtxu0y03dxlaZPZa9Uccu0B-GRmuRN_L_UqbvmIQywbJrauDt5IiwHOoA0XbUGb8Yrh8G3lB8Pt3MyuzCMuZIByCMba5XNun0xF7Y0PVKE//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/4119803614588237986/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-element-component.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4119803614588237986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4119803614588237986'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs-element-component.html' title='Vue.js - 加入 Element Component'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32uR_eGxzFkHQxWOFC4YjtIVsxx_ICKeLWJwIop6uIJLZX1w0Djbk1fu7u3IDaF-M-rS27vTb_oQL9AeWjxXHzfkNHoCqQgmRVeJcqCrtsf9-AeChfqmYVqpUa07z165YZBmmTa3Kk0w/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-4251112051068100233</id><published>2017-12-25T10:42:00.001+08:00</published><updated>2017-12-29T19:15:31.387+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="vue.js"/><title type='text'>Vue.js 初體驗</title><content type='html'>&lt;p&gt;開始學 Vue.js 時，發現這幾年的 Web UI 真的變化很大. 由其是從 node.js 出來之後由其明顯.只好惡補一下 npm, webpack 這些技術好得以入門. 但其細節的設定還是要慢慢的深入.沒辦法一口吃不成胖子啊.&lt;/p&gt;&lt;p&gt;在寫 Vue.js 中其官方文件 ( &lt;a title=&quot;https://cn.vuejs.org/v2/guide/installation.html&quot; href=&quot;https://cn.vuejs.org/v2/guide/installation.html&quot;&gt;https://cn.vuejs.org/v2/guide/installation.html&lt;/a&gt; ) 真的幫助很大.依官方文件步驟一個基本上的 vue project基本上的配置都幫你搞定了. &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiohbFammLhoDZZwYxizp9G8y4s7Wh01w1dKF46BsCrWbPIGcnXSo419Yhkum5b_kBN3WVURjFZR-J1J0XqnGO8l6CHmYkdgu52KztBVlRYXtJqkUGmMnPb6S63RqIyQDsuPl9p-_xDcXg/s1600-h/image3&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;208&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2h85AXPzkqect8rTevTna_jxDIKPsLoRkrLBVIwE3Ldc-5oTcXkO1_yjD5fhpxlSH1mrNiKqvBD0XFAvwlOQxWG2dNucP_yz6Hkkf1EIltZtj4Yb9sYrxnnNCq0bBVtFxErjGU5QZIuw//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Q3nyTAj2zTbpadMbh7DW6Dh7ybFXtYOlZNXAtQNa-UcEo5jeo4YzKIg7F_2U1EeaL1FHvOrLOb4q8pPnOHErclOu7K9s_sbbVX0egdIEUWlGOSOLzkZKxOrHph23lxGaI29CNEfgRBk/s1600-h/image13&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;233&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCcb_K9ceXiJznmKobwN4VBa4oAkl9Hv390cI7hGWyyIdOdCe9b64WELNjdAZKfRFUWUFmMi2bg3P2A4rmHxW3UTOqqd9QOs2BhD-mC4R8LAFzPeoYGXSTFzZLUT4Oz_60xGyPDHZC8KA//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最後依其步驟執執行是否建立成功.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUd8uvgHx_bQrkB1UxTa1j2HxhI9RpzhcwUrRIkxrjABubzuBdEoZlfQkrmr7QRBObVlXlrkysu0A6PwNEHchye8QOfSt4bW1e7LqZTEDh5zTMdhXuWjrFB4vNYomRxxVMmWa5FkwWuhI/s1600-h/image14&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;503&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQVqln8eO068Kl4gHHAT3DS7IcqvvQW_vw3Nj_u0dRX76XQoBVoEoZagqkuwNGLxOtZtIFPDNGbIhmlfrKteI-OjXn1sdmCDwYofIsiA5UMnIsy320y1CoblUu0S-mq-FOR9HDdcY_-3M//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;接著試修改一下其內容. 開始 App.vue file. &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbZjSO6LelKzDhO1BpVAyDFECrNLuJnibPDj6n32VdBkIa6hzUimgJOLvQ4uJRqdA5HsRDIwdHYULeHudd9Nn9ePrvWm-MHIFzG3-5Y9IGuA9OypYBOLLgEtzzKk5gl-fEJb3_NjvxNg/s1600-h/image%255B4%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;721&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGa0z6z61W3EYew8EOaG0coUo9kB98jEhKzasWW-LwidZcBsIDpOdchr-Fj_x9xINiJBACjHUnuZyxXCA4yrdeNxohxOGdHIJBUYkRpMO8bOQ8EbXeXpZJ_gDhSxFtJ7eilS_rINkBa4U//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;再來查看一下畫面，即可看到大大的 “ &lt;font color=&quot;#ff0000&quot; size=&quot;5&quot;&gt;&lt;strong&gt;Hello World&lt;/strong&gt;&lt;/font&gt; ”，第一個 vue project 完成了….&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiH4kQzTCZNR7vmvar3xeuKgKcaVZ2zDYPoaAEBmnpw-LX0s-wd6m8RsGThAi65VuPdI7utC_Byd2AQGorpW8RfQw7uMfxzjN2KFhIybj_V8QOnImfipPRhtujrF8cf418DRUs_-JBz5o/s1600-h/image%255B8%255D&quot;&gt;&lt;img width=&quot;548&quot; height=&quot;528&quot; title=&quot;image&quot; style=&quot;display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJKYRU7pygf9T7Epbr9PitY7ayirRzkt21cvm1qtd3ebzMr-ryXI4XWrF9LjE2RDKO10TTW_lyN8EYl9LLy2eVpCRZlhdh-hnomBvoJs3hcLZ2nc3DSGwC_itR0puJa6BeYmdMH23EmRo//?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/4251112051068100233/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4251112051068100233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4251112051068100233'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2017/12/vuejs.html' title='Vue.js 初體驗'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2h85AXPzkqect8rTevTna_jxDIKPsLoRkrLBVIwE3Ldc-5oTcXkO1_yjD5fhpxlSH1mrNiKqvBD0XFAvwlOQxWG2dNucP_yz6Hkkf1EIltZtj4Yb9sYrxnnNCq0bBVtFxErjGU5QZIuw/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-4906958603042236281</id><published>2014-01-09T10:24:00.001+08:00</published><updated>2014-01-09T10:24:11.578+08:00</updated><title type='text'>Java’s Hibernate – Timestamp 造成 performance slow 的問題</title><content type='html'>&lt;h4&gt;&lt;font style=&quot;font-weight: normal&quot; size=&quot;2&quot;&gt;Oracle 在使用 Hibernate 時, 其 Condition 中有 Timestamp 時會造成 performance slow 的問題, 從官網上看到這篇在此記錄一下.&lt;/font&gt;&lt;/h4&gt; &lt;h4&gt;&amp;nbsp;&lt;/h4&gt; &lt;h4&gt;Simple Data Types&lt;/h4&gt;&lt;strong&gt;&lt;a name=&quot;08_01&quot;&gt;&lt;/a&gt;What is going on with &lt;tt&gt;DATE&lt;/tt&gt; and &lt;tt&gt;TIMESTAMP&lt;/tt&gt;? &lt;/strong&gt; &lt;p&gt;This section is on &lt;strong&gt;simple&lt;/strong&gt; data types. :-)  &lt;p&gt;Prior to 9.2, the Oracle JDBC drivers mapped the &lt;tt&gt;DATE&lt;/tt&gt; SQL type to &lt;tt&gt;java.sql.Timestamp&lt;/tt&gt;. This made a certain amount of sense because the Oracle &lt;tt&gt;DATE&lt;/tt&gt; SQL type contains both date and time information as does &lt;tt&gt;java.sql.Timestamp&lt;/tt&gt;. The more obvious mapping to &lt;tt&gt;java.sql.Date&lt;/tt&gt; was somewhat problematic as &lt;tt&gt;java.sql.Date&lt;/tt&gt; does not include time information. It was also the case that the RDBMS did not support the &lt;tt&gt;TIMESTAMP&lt;/tt&gt; SQL type, so there was no problem with mapping &lt;tt&gt;DATE&lt;/tt&gt; to &lt;tt&gt;Timestamp&lt;/tt&gt;.  &lt;p&gt;In 9.2 &lt;tt&gt;TIMESTAMP&lt;/tt&gt; support was added to the RDBMS. The difference between &lt;tt&gt;DATE&lt;/tt&gt; and &lt;tt&gt;TIMESTAMP&lt;/tt&gt; is that &lt;tt&gt;TIMESTAMP&lt;/tt&gt; includes nanoseconds and &lt;tt&gt;DATE&lt;/tt&gt; does not. So, beginning in 9.2, &lt;tt&gt;DATE&lt;/tt&gt; is mapped to &lt;tt&gt;Date&lt;/tt&gt; and &lt;tt&gt;TIMESTAMP&lt;/tt&gt; is mapped to &lt;tt&gt;Timestamp&lt;/tt&gt;. Unfortunately if you were relying on &lt;tt&gt;DATE&lt;/tt&gt; values to contain time information, there is a problem.  &lt;p&gt;There are several ways to address this problem in the 9.2 through 10.2 drivers: &lt;ul&gt; &lt;li&gt; &lt;p&gt;Alter your tables to use &lt;tt&gt;TIMESTAMP&lt;/tt&gt; instead of &lt;tt&gt;DATE&lt;/tt&gt;. This is probably rarely possible, but it is the best solution when it is. &lt;/p&gt; &lt;li&gt; &lt;p&gt;Alter your application to use &lt;tt&gt;defineColumnType&lt;/tt&gt; to define the columns as &lt;tt&gt;TIMESTAMP&lt;/tt&gt; rather than &lt;tt&gt;DATE&lt;/tt&gt;. There are problems with this because you really don&#39;t want to use &lt;tt&gt;defineColumnType&lt;/tt&gt; unless you have to (see &lt;a href=&quot;http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#06_01&quot;&gt;What is &lt;tt&gt;defineColumnType&lt;/tt&gt; and when should I use it? &lt;/a&gt;). &lt;/p&gt; &lt;li&gt; &lt;p&gt;Alter you application to use &lt;tt&gt;getTimestamp&lt;/tt&gt; rather than &lt;tt&gt;getObject&lt;/tt&gt;. This is a good solution when possible, however many applications contain generic code that relies on &lt;tt&gt;getObject&lt;/tt&gt;, so it isn&#39;t always possible. &lt;/p&gt; &lt;li&gt; &lt;p&gt;Set the &lt;tt&gt;V8Compatible&lt;/tt&gt; connection property. This tells the JDBC drivers to use the old mapping rather than the new one. You can set this flag either as a connection property or a system property. You set the connection property by adding it to the &lt;tt&gt;java.util.Properties&lt;/tt&gt; object passed to &lt;tt&gt;DriverManager.getConnection&lt;/tt&gt; or to &lt;tt&gt;OracleDataSource.setConnectionProperties&lt;/tt&gt;. You set the system property by including a &lt;tt&gt;-D&lt;/tt&gt; option in your &lt;tt&gt;java&lt;/tt&gt; command line.  &lt;p&gt;java -Doracle.jdbc.V8Compatible=&quot;true&quot; MyApp&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Oracle JDBC 11.1 fixes this problem. Beginning with this release the driver maps SQL DATE columns to &lt;tt&gt;java.sql.Timestamp&lt;/tt&gt; by default. There is no need to set &lt;tt&gt;V8Compatible&lt;/tt&gt; to get the correct mapping. &lt;tt&gt;V8Compatible&lt;/tt&gt; is strongly deprecated. You should not use it at all. If you do set it to true it won&#39;t hurt anything, but you should stop using it.  &lt;p&gt;Although it was rarely used that way, &lt;tt&gt;V8Compatible&lt;/tt&gt; existed not to fix the DATE to Date issue but to support compatibility with 8i databases. 8i (and older) databases did not support the TIMESTAMP type. Setting &lt;tt&gt;V8Compatible&lt;/tt&gt; not only caused SQL DATE to be mapped to &lt;tt&gt;Timestamp&lt;/tt&gt; when read from the database, it also caused all &lt;tt&gt;Timestamps&lt;/tt&gt; to be converted to SQL DATE when written to the database. Since 8i is desupported, the 11.1 JDBC drivers do not support this compatibility mode. For this reason &lt;tt&gt;V8Compatible&lt;/tt&gt; is desupported.  &lt;p&gt;As mentioned above, the 11.1 drivers by default convert SQL DATE to &lt;tt&gt;Timestamp&lt;/tt&gt; when reading from the database. This always was the right thing to do and the change in 9i was a mistake. The 11.1 drivers have reverted to the correct behavior. Even if you didn&#39;t set &lt;tt&gt;V8Compatible&lt;/tt&gt; in your application you shouldn&#39;t see any difference in behavior in most cases. You may notice a difference if you use getObject to read a DATE column. The result will be a &lt;tt&gt;Timestamp&lt;/tt&gt; rather than a &lt;tt&gt;Date&lt;/tt&gt;. Since &lt;tt&gt;Timestamp&lt;/tt&gt; is a subclass of &lt;tt&gt;Date&lt;/tt&gt; this generally isn&#39;t a problem. Where you might notice a difference is if you relied on the conversion from DATE to &lt;tt&gt;Date&lt;/tt&gt; to truncate the time component or if you do toString on the value. Otherwise the change should be transparent.  &lt;p&gt;If for some reason your app is very sensitive to this change and you simply must have the 9i-10g behavior, there is a connection property you can set. Set &lt;tt&gt;mapDateToTimestamp&lt;/tt&gt; to false and the driver will revert to the default 9i-10g behavior and map DATE to &lt;tt&gt;Date&lt;/tt&gt;. &lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/4906958603042236281/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2014/01/javas-hibernate-timestamp-performance.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4906958603042236281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4906958603042236281'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2014/01/javas-hibernate-timestamp-performance.html' title='Java’s Hibernate – Timestamp 造成 performance slow 的問題'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-3644725649661625226</id><published>2013-10-28T11:33:00.001+08:00</published><updated>2013-10-28T11:33:30.171+08:00</updated><title type='text'>Hadoop 的介紹</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最近開始接觸 Hadoop 及 MapReduce 的部份! 好吧~剛好看到不錯的 vedio 在做介紹,把它記錄一下, 以備不時之需.&lt;/p&gt; &lt;p&gt;Introduction to Hadoop&lt;br&gt;&lt;iframe height=&quot;375&quot; src=&quot;//player.vimeo.com/video/12873553&quot; width=&quot;500&quot; allowfullscreen mozallowfullscreen webkitallowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;Destributed System Overview&lt;br&gt;&lt;iframe height=&quot;375&quot; src=&quot;//player.vimeo.com/video/12869710&quot; width=&quot;500&quot; allowfullscreen mozallowfullscreen webkitallowfullscreen&gt;&lt;/iframe&gt; &lt;p&gt;來源 : &lt;a title=&quot;http://www.wretch.cc/blog/trendnop09/21756796&quot; href=&quot;http://www.wretch.cc/blog/trendnop09/21756796&quot;&gt;http://www.wretch.cc/blog/trendnop09/21756796&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/3644725649661625226/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/10/hadoop.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3644725649661625226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3644725649661625226'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/10/hadoop.html' title='Hadoop 的介紹'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-9120928389327430879</id><published>2013-08-29T15:34:00.001+08:00</published><updated>2013-08-29T15:34:50.374+08:00</updated><title type='text'>WPF – InvokeCommandAction 的使用</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在使用 MVVM 的架構時, 都會使用 Command 來 Handle 所觸發的 Event, 但如果其控制項沒有提供 Command 時, 此時又該如何呢？在 WPF 中提供了 InvokeCommandAction 這個 Class, 它提供控制項在觸發其 Event 時所需的 Handle，讓 develper 人員可以任意的 hanlde 所需的 Event. 下面的例如使用 InvokeCommandAction handle ComboBox 控制項當 select item changed 所觸發 SelectionChanged 的 Event.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 124px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 99.1%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;ComboBox Width=&quot;180&quot; Margin=&quot;3&quot; HorizontalAlignment=&quot;Left&quot; VerticalAlignment=&quot;Top&quot;&amp;gt;&lt;br /&gt;    &amp;lt;i:Interaction.Triggers&amp;gt;&lt;br /&gt;        &amp;lt;i:EventTrigger EventName=&quot;SelectionChanged&quot;&amp;gt;&lt;br /&gt;            &amp;lt;i:InvokeCommandAction Command=&quot;{Binding StepIdChangedCommand}&quot; /&amp;gt;&lt;br /&gt;        &amp;lt;/i:EventTrigger&amp;gt;&lt;br /&gt;    &amp;lt;/i:Interaction.Triggers&amp;gt;&lt;br /&gt;&amp;lt;/ComboBox&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/9120928389327430879/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/08/wpf-invokecommandaction.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/9120928389327430879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/9120928389327430879'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/08/wpf-invokecommandaction.html' title='WPF – InvokeCommandAction 的使用'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-1907689837615974939</id><published>2013-08-21T09:17:00.001+08:00</published><updated>2013-08-21T09:17:52.473+08:00</updated><title type='text'>C# – 統計 Percentile 函數</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最近一直聽到 P25, P50, P75, P95 這種統計數值, 那在 .NET 中並沒有相對映的函數可以使用, 故在網路上看到了有人提供的此函數的寫法, 故在此記錄一下. &lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 240px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.56%; background-color: #eee&quot;&gt;&lt;code&gt;public double Percentile(double[] sequence, double excelPercentile)&lt;br /&gt;{&lt;br /&gt;    Array.Sort(sequence);&lt;br /&gt;    int N = sequence.Length;&lt;br /&gt;    double n = (N - 1) * excelPercentile + 1;&lt;br /&gt;    // Another method: double n = (N + 1) * excelPercentile;&lt;br /&gt;    if (n == 1d) return sequence[0];&lt;br /&gt;    else if (n == N) return sequence[N - 1];&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;         int k = (int)n;&lt;br /&gt;         double d = n - k;&lt;br /&gt;         return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/1907689837615974939/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/08/c-percentile.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1907689837615974939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1907689837615974939'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/08/c-percentile.html' title='C# – 統計 Percentile 函數'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-2276833096625618767</id><published>2013-06-13T15:20:00.001+08:00</published><updated>2013-06-13T15:20:54.568+08:00</updated><title type='text'>WPF – Getting Started with MVVM</title><content type='html'>&lt;p&gt;I&#39;ve been working with MVVM and WPF for a couple of weeks now. I decided to log what I&#39;ve learned here. Here goes a getting started tutorial with MVVM.  &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;http://dl.dropbox.com/u/8855362/blog/uploads/MvvmStarter.zip&quot;&gt;Download the source code&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The Model-View-ViewModel pattern was introduced by &lt;a href=&quot;http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx&quot;&gt;John Gossman&lt;/a&gt; to effectively utilize the functionality of WPF. Since then, MVVM has been used in a number of WPF applications with very impressive results. MVVM has three components:  &lt;ul&gt; &lt;li&gt;&lt;em&gt;&lt;em&gt;Model:&lt;/em&gt;&lt;/em&gt; It is your data or classes that represent entities in your application. It normally contains no WPF-specific code.  &lt;li&gt;&lt;em&gt;&lt;em&gt;View:&lt;/em&gt;&lt;/em&gt; This is the User Interface element visible to the user. Its DataContext is its ViewModel.  &lt;li&gt;&lt;em&gt;&lt;em&gt;ViewModel:&lt;/em&gt;&lt;/em&gt; It contains all the data that needs to be displayed and procedures to modify the model at will. The magic about MVVM is that the ViewModel knows nothing about the View.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You see that this is very loosely coupled. The View knows the ViewModel but the ViewModel does not know the View. You can very easily replace the View without affecting the ViewModel. This is very useful in Developer/Designer teams where the Developer improves the ViewModel and the Designer enhances the View.  &lt;p&gt;The fact that the ViewModel does not know anything about the View comes as a bit of surprise. There is one more surprise: a typical View in MVVM does not need a code-behind (except for the general boiler-plate code that calls the InitializeComponent() method from the constructor)!  &lt;p&gt;You may be wondering how the view updates itself when the ViewModel changes and how it handles user interaction like button clicks etc. This is what makes MVVM specific to WPF.  &lt;p&gt;The controls in the View bind themselves to the corresponding properties in the ViewModel. The changes in ViewModel will be reflected in the view, thanks to Data Binding in WPF. (Otherwise we would have had to handle every event and then update the view accordingly.)  &lt;p&gt;As for user interaction, we always have had commands in WPF. MVVM leverages on this feature. Instead of writing event handling code for button clicks, we bind the buttons (or MenuItems) to Commands in the ViewModel. Every button (even the SaveCustomer, CloseTab etc.) binds itself to a command which the ViewModel exposes. This command delegates its job to a method in the ViewModel that gets the work done. But the problem is that there is no built-in command in WPF that does that. We have a RoutedCommand that targets UIElements but not methods. Here comes to the scene a new command that targets methods, the DelegateCommand or the RelayCommand. Controls can bind the RelayCommand (that the ViewModel exposes) and invoke methods in the ViewModel.  &lt;p&gt;The DelegateCommand implements the ICommand interface and delegates the Execute and CanExecute methods in the interface to methods in the ViewModel.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 603px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.73%; background-color: #eee&quot;&gt;&lt;code&gt;using System;&lt;br /&gt;using System.Windows.Input;&lt;br /&gt;&lt;br /&gt;namespace MvvmSample&lt;br /&gt;{&lt;br /&gt;    public class DelegateCommand : ICommand&lt;br /&gt;    {&lt;br /&gt;        readonly Action&amp;lt;object&amp;gt; _execute;&lt;br /&gt;        readonly Predicate&amp;lt;object&amp;gt; _canExecute;&lt;br /&gt;&lt;br /&gt;        public DelegateCommand(Action&amp;lt;object&amp;gt; execute) : this(execute, null)&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public DelegateCommand(Action&amp;lt;object&amp;gt; execute, Predicate&amp;lt;object&amp;gt; canExecute)&lt;br /&gt;        {&lt;br /&gt;            if (execute == null)&lt;br /&gt;                throw new ArgumentNullException(&quot;execute&quot;);&lt;br /&gt;&lt;br /&gt;            _execute = execute;&lt;br /&gt;            _canExecute = canExecute;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Execute(object parameter)&lt;br /&gt;        {&lt;br /&gt;            _execute(parameter);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public bool CanExecute(object parameter)&lt;br /&gt;        {&lt;br /&gt;            return _canExecute == null ? true : _canExecute(parameter);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public event EventHandler CanExecuteChanged&lt;br /&gt;        {&lt;br /&gt;            add { CommandManager.RequerySuggested += value; }&lt;br /&gt;            remove { CommandManager.RequerySuggested -= value; }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now we are going to create a simple tabbed interface. When you File-&amp;gt;New Tab, a new tab opens up. When you click File-&amp;gt;Exit, the application closes. You may think that this is very simple but achieving this in MVVM needs a lot of ground on it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Open a new WPF application. Change the Window1 to MainWindow (I just hate Window1). Replace the Grid element in the MainWindow with the following markup.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 166px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.74%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;DockPanel&amp;gt;&lt;br /&gt;    &amp;lt;Menu DockPanel.Dock=&quot;Top&quot;&amp;gt;&lt;br /&gt;        &amp;lt;MenuItem Header=&quot;_File&quot;&amp;gt;&lt;br /&gt;            &amp;lt;MenuItem Header=&quot;New _Tab&quot; /&amp;gt;&lt;br /&gt;            &amp;lt;Separator /&amp;gt;&lt;br /&gt;            &amp;lt;MenuItem Header=&quot;E_xit&quot; /&amp;gt;&lt;br /&gt;        &amp;lt;/MenuItem&amp;gt;&lt;br /&gt;    &amp;lt;/Menu&amp;gt;&lt;br /&gt;    &amp;lt;TabControl /&amp;gt;&lt;br /&gt;&amp;lt;/DockPanel&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;You know it simply adds a menu to the top and a tab control. Now we create a simple MainWindowViewModel class. Since the View binds its controls to the Properties in the ViewModel, we need to implement the INotifyPropertyChanged interface. But in this example we are not going to need it. Create an empty class MainWindowViewModel. &lt;br /&gt;&lt;p&gt;We know that the view sets its DataContext to the ViewModel. We&#39;ll use the Application class to set it for the view. Remove the StartupUri attribute from the &lt;code&gt;Application.xaml&lt;/code&gt; file and override the &lt;code&gt;OnStartup&lt;/code&gt; method to initialize a new &lt;code&gt;MainWindow&lt;/code&gt; and a new &lt;code&gt;MainWindowViewModel&lt;/code&gt;, set the &lt;code&gt;DataContext&lt;/code&gt; of the &lt;code&gt;MainWindow&lt;/code&gt; to the &lt;code&gt;MainViewModel&lt;/code&gt;, set the &lt;code&gt;MainWindow&lt;/code&gt; property of &lt;code&gt;Application&lt;/code&gt; class this &lt;code&gt;MainWindow&lt;/code&gt; and finally show the &lt;code&gt;MainWindow&lt;/code&gt;. &lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 143px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.2%; background-color: #eee&quot;&gt;&lt;code&gt;protected override void OnStartup(StartupEventArgs e)&lt;br /&gt;{&lt;br /&gt;    MainWindow mainWindow = new MainWindow();&lt;br /&gt;    MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();&lt;br /&gt;    mainWindow.DataContext = mainWindowViewModel;&lt;br /&gt;    base.MainWindow = mainWindow;&lt;br /&gt;    mainWindow.Show();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now we have setup the base for MVVM. But our application does nothing. When we click New Tab or Exit nothing happens. To hook this up, we need a command. Let&#39;s first implement the Exit Command. In the MainWindowViewModel, add a new DelegateCommand, ExitCommand.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 242px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.67%; background-color: #eee&quot;&gt;&lt;code&gt;private DelegateCommand exitCommand;&lt;br /&gt;public ICommand ExitCommand&lt;br /&gt;{&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;        if(exitCommand == null)&lt;br /&gt;            exitCommand = new DelegateCommand(Exit);&lt;br /&gt;        return exitCommand;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void Exit(object obj) &lt;br /&gt;{&lt;br /&gt;    Application.Current.Shutdown();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now when the Execute() method on ExitCommand is called, Exit method is invoked. We use the Exit method to shutdown the application. Now all we have to do is bind the Exit menu item to this command. When you click Exit, the Exit method is called and the application shuts down.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 41px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.73%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;MenuItem Header=&quot;E_xit&quot; Command=&quot;{Binding ExitCommand}&quot; /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now, let&#39;s implement the Add Tab functionality. Obviously, we need a new command, AddTabCommand.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 239px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.93%; background-color: #eee&quot;&gt;&lt;code&gt;private DelegateCommand addTabCommand;&lt;br /&gt;public ICommand AddTabCommand&lt;br /&gt;{&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;        if (addTabCommand == null)&lt;br /&gt;            addTabCommand = new DelegateCommand(AddTab);&lt;br /&gt;        return addTabCommand;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void AddTab(object obj)&lt;br /&gt;{&lt;br /&gt;    throw new NotImplementedException();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Here we have a problem. The ViewModel does not know the View and does not know the TabControl in it. How is it going to add a tab into that TabControl? If it were a simple code-behind, we would have given the tab control a name and hooked up an event handler to add a new tab to the control. But what do we do now? Any guesses? &lt;br /&gt;&lt;p&gt;Let&#39;s use a trick. We know the View can modify itself to reflect changes in the ViewModel. Let&#39;s exploit this. We will maintain a list of tabs in the ViewModel and the TabControl binds itself to this list. Now if we add a new item in the list, a new tab is added in the view! Wonderful! &lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 112px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.56%; background-color: #eee&quot;&gt;&lt;code&gt;public ObservableCollection&amp;lt;TabItem&amp;gt; Tabs { get; set; }&lt;br /&gt;&lt;br /&gt;public MainWindowViewModel()&lt;br /&gt;{&lt;br /&gt;    Tabs = new ObservableCollection&amp;lt;TabItem&amp;gt;();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We need an observable collection to bind lists (It&#39;s why we did not need to implement the INotifyPropertyChanged explicitly here). Now, we need to bind the TabControl to this collection.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 54px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.92%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;TabControl ItemsSource=&quot;{Binding Tabs}&quot; /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now, the AddTab method adds a new TabItem into the list and the View updates itself.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 128px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.73%; background-color: #eee&quot;&gt;&lt;code&gt;private void AddTab(object obj)&lt;br /&gt;{&lt;br /&gt;    TabItem tab = new TabItem();&lt;br /&gt;    tab.Header = &quot;New Tab&quot;;&lt;br /&gt;    Tabs.Add(tab);&lt;br /&gt;    tab.Focus();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The last thing to do is to hook up the Add Tab MenuItem to the AddTabCommand.&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 40px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 99.1%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;MenuItem Header=&quot;New _Tab&quot; Command=&quot;{Binding AddTabCommand}&quot; /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Excellent! It&#39;s all working very well. This is all about MVVM in its simplest way. You can see how easy it is to have everything separated and implement a very loosely coupled application. MVVM lets you unit test your software and change the views very easily.&lt;br /&gt;&lt;p&gt;You can notice that in this example, the ViewModel &lt;em&gt;does&lt;/em&gt; know something about the View. It knows that the view contains a TabControl and adds TabItems to it. You &lt;em&gt;must&lt;/em&gt; remove this dependency. I wanted this post to be as simple as it could be. However, that will be part of my upcoming posts. Now that you have set for yourself a base, explore the fantastic world of WPF and MVVM. Good Luck!&lt;br /&gt;&lt;p&gt;轉貼 : &lt;a href=&quot;http://codingtales.com/2010/01/12/getting-started-with-mvvm-in-wpf&quot; target=&quot;_blank&quot;&gt;Getting Started With MVVM in WPF&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/2276833096625618767/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-getting-started-with-mvvm.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2276833096625618767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2276833096625618767'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-getting-started-with-mvvm.html' title='WPF – Getting Started with MVVM'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-5179589113517004777</id><published>2013-06-13T14:23:00.001+08:00</published><updated>2013-06-13T14:23:09.712+08:00</updated><title type='text'>WPF - 深入 Style</title><content type='html'>&lt;blockquote&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 44px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 100.55%; background-color: #eee&quot;&gt;&lt;code&gt;&lt;a href=&quot;http://msdn.microsoft.com/zh-cn/library/system.windows.style.aspx&quot; target=&quot;_blank&quot;&gt;Style&lt;/a&gt; 用來在類型的不同實例之間共享屬性、資源和事件處理程序，您可以將 &lt;a href=&quot;http://msdn.microsoft.com/zh-cn/library/system.windows.style.aspx&quot; target=&quot;_blank&quot;&gt;Style&lt;/a&gt; 看作是將一組屬性值應用到多個元素的捷徑。 &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;　　這是MSDN上對Style的描述，翻譯的還算中規中矩。Style（樣式），簡單來說，就是一種對屬性值的批處理，類似于Html的CSS，可以快速的設置一系列屬性值到UI元素。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;示例&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　一個最簡單的Style的例子：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 197px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 90.83%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Grid&amp;gt;&lt;br /&gt;        &amp;lt;Grid.Resources&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type Button}&quot; x:Key=&quot;ButtonStyle&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Height&quot; Value=&quot;22&quot;/&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;60&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;/Grid.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Button Content=&quot;Button&quot; Style=&quot;{StaticResource ButtonStyle}&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;Button Content=&quot;Button&quot; Style=&quot;{StaticResource ButtonStyle}&quot; Margin=&quot;156,144,286,145&quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　關于Resources的知識，請參見&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms742538.aspx&quot;&gt;MSDN&lt;/a&gt;，這里創建了一個目標類型為Button的ButtonStyle，兩個Button使用靜態資源（&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms750950.aspx&quot;&gt;StaticResource&lt;/a&gt;）的查找方式來找到這個Style。Style中定義了Button的高度（Height）和寬度（Width），當使用了這個Style后，兩個Button無需手動設置，即可自動設置它們的高度和寬度為ButtonStyle的預設值22和60。 &lt;br /&gt;&lt;p&gt;　　Style作為屬性，資源，事件的批處理，它提供了一種捷徑來對控件進行快速設置，使用Style的好處有二： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;把一些控件的通用設置抽出來變成Style，使這些控件具有統一的風格，修改Style中的屬性值可以方便的作用在所有應用該Style的控件上。 &lt;br /&gt;&lt;li&gt;可以對同一類型控件定義多個Style，通過替換Style來方便的更改控件的樣式。 &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h3&gt;Style的元素&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　上面Style的例子中，Style內部使用了Setter來定義控件屬性的預設值，Style不僅支持對屬性的批處理，也可以共享資源和事件處理，如：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 381px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 87.97%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Window.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type Button}&quot; x:Key=&quot;ButtonStyle&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Style.Resources&amp;gt;&lt;br /&gt;                &amp;lt;SolidColorBrush x:Key=&quot;brush&quot; Color=&quot;Yellow&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style.Resources&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Height&quot; Value=&quot;22&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;60&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;EventSetter Event=&quot;Loaded&quot; Handler=&quot;Button_Loaded&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;/Window.Resources&amp;gt;&lt;br /&gt;    &amp;lt;x:Code&amp;gt;&lt;br /&gt;        &amp;lt;![CDATA[&lt;br /&gt;            void Button_Loaded(object sender, RoutedEventArgs e)&lt;br /&gt;            {&lt;br /&gt;                MessageBox.Show((sender as Button).Name + &quot; Loaded&quot;);&lt;br /&gt;            }&lt;br /&gt;        ]]&amp;gt;&lt;br /&gt;    &amp;lt;/x:Code&amp;gt;&lt;br /&gt;    &amp;lt;Grid&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button1&quot; Style=&quot;{StaticResource ButtonStyle}&quot; Background=&quot;{DynamicResource brush}&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button2&quot; Style=&quot;{StaticResource ButtonStyle}&quot; Background=&quot;{DynamicResource brush}&quot; Margin=&quot;156,144,286,145&quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　Style中定義了資源SolidColorBrush，定義了屬性Height和Width，以及使用了EventSetter來定義了Loaded事件的處理。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Trigger&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　Style使用了Setter和EventSetter來分別設置控件的屬性和事件處理，Setter這個單詞的含義是設置。Style在設計好了這兩種設置后，又引入了更先進的思路：條件設置。 &lt;br /&gt;&lt;p&gt;　　對于單純的Setter：&amp;lt;Setter Property=”Height” Value=”22”&amp;gt;來說，含義淺顯易懂：設置高度為22。條件設置的含義是，在某種條件下，去設置某個對象的某個值。 &lt;br /&gt;&lt;p&gt;　　WPF引入了Trigger（触發器）來触發這個條件，它的寫法是：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 145px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 90.58%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Style TargetType=&quot;{x:Type Button}&quot; x:Key=&quot;ButtonStyle&quot;&amp;gt;&lt;br /&gt;    &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;60&quot;/&amp;gt;&lt;br /&gt;    &amp;lt;Style.Triggers&amp;gt;&lt;br /&gt;        &amp;lt;Trigger Property=&quot;IsMouseOver&quot; Value=&quot;True&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;80&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Trigger&amp;gt;&lt;br /&gt;    &amp;lt;/Style.Triggers&amp;gt;&lt;br /&gt;&amp;lt;/Style&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　這里Trigger的含義是，在Button的IsMouseOver屬性被設置為True的條件下，設置Button的寬度（Width）為80。 &lt;br /&gt;&lt;p&gt;　　在Style中，不需要指定Setter作用的對象（TargetName），默認作用的對象就是使用該Style的控件。Trigger，作為触發器，當触發時設置寬度為80，當IsMouseOver屬性為False，也就是触發條件失效時，寬度回到默認Setter的設置值60。 &lt;br /&gt;&lt;p&gt;　　WPF定義了五種Trigger來作為触發條件，分別是：Trigger，DataTrigger，MultiTrigger，MultiDataTrigger，EventTrigger，他們的触發條件分別是： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Trigger：以控件的屬性作為触發條件，如前面的IsMouseOver為True的時候触發。 &lt;br /&gt;&lt;li&gt;DataTrigger：以控件DataContext的屬性作為触發條件。 &lt;br /&gt;&lt;li&gt;MultiTrigger：以控件的多個屬性作為触發條件。 &lt;br /&gt;&lt;li&gt;MultiDataTrigger：以控件DataContext的多個屬性作為触發條件。 &lt;br /&gt;&lt;li&gt;EventTrigger：以RoutedEvent作為触發條件，當指定的路由事件Raise時触發。 &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　關于這5種Trigger的具體使用，請參見&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms745683.aspx&quot;&gt;MSDN&lt;/a&gt;，這里就不詳細介紹了。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Implicit Style&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　上面的例子中，都是使用&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms750950.aspx&quot;&gt;StaticResource&lt;/a&gt;來設置Style的，當然，你也可以使用&lt;a href=&quot;http://msdn.microsoft.com/zh-cn/library/ms748942.aspx&quot;&gt;DynamicResource&lt;/a&gt;來設置Style。這兩種方式都需要你在XAML或者后台代碼中手動注明，為了使用方便，WPF提出了隱式（Implicit） Style的方式允許自動設置Style到控件，如：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 220px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.42%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Grid&amp;gt;&lt;br /&gt;        &amp;lt;Grid.Resources&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type Button}&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Height&quot; Value=&quot;22&quot;/&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;60&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;/Grid.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button1&quot; Style=&quot;{x:Null}&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button2&quot; Margin=&quot;156,144,286,145&quot; /&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button3&quot; Margin=&quot;196,144,0,145&quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　在Gird的Resource中定義Style時，沒有給Style起名字（Key），這個Style會自動應用在Grid的所有子Button中，如果像button1一樣在Button中顯式定義了Style（這里設置了一個空值Null），那麼這種隱式（Implicit）的Style會不起作用。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;深入Style&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　Style是一個不錯的概念，作為一個Presentation的框架，把UI對象的結构，樣式和行為分離這是一種很好的設計。Style也比較容易上手，像它的隱式（Implicit）Style的設計也是水到渠成的想法，但實際使用中也會出現一些問題。這些問題在WPF中也會經常遇見：概念不錯，描述簡單，前景美好，Bug稀奇古怪，要把這些問題說清楚，就要從根本來看，Style是個什麼東西？ &lt;br /&gt;&lt;p&gt;　　按照通常的想法，Style應該類似于一個Dictionary&amp;lt;string, object&amp;gt; setters，預存了屬性的名字和預設值，然后作用到UI對象上。WPF在Style處的想法很多，圍繞著几個關鍵技朮也加入了很多功能，詳細的介紹一下： &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Style &amp;amp; Dependency Property&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　Dependency Property（簡稱DP）是WPF的核心，Style就是基于Dependency Property的，關于DP的內幕，請參見&lt;a href=&quot;http://www.cnblogs.com/Zhouyongh/archive/2009/09/10/1564099.html&quot;&gt;深入WPF--依賴屬性&lt;/a&gt;。Style中的Setter就是作用在DP上的，如果你在控件中定義了一個CLR屬性，Style是不能設置的。Dependency Property設計的精髓在于把字段的存取和對象（Dependency Object）剝離開，一個屬性值內部用多個字段來存儲，根据取值條件的優先級來決定當前屬性應該取哪個字段。 &lt;br /&gt;&lt;p&gt;　　Dependency Property取值條件的優先級是（從上到下優先級從低到高）：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 245px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.57%; background-color: #eee&quot;&gt;&lt;code&gt;public enum BaseValueSource&lt;br /&gt;{&lt;br /&gt;    Unknown,&lt;br /&gt;    Default,&lt;br /&gt;    Inherited,&lt;br /&gt;    DefaultStyle,&lt;br /&gt;    DefaultStyleTrigger,&lt;br /&gt;    Style,&lt;br /&gt;    TemplateTrigger,&lt;br /&gt;    StyleTrigger&lt;br /&gt;    ImplicitStyleReference,&lt;br /&gt;    ParentTemplate,&lt;br /&gt;    ParentTemplateTrigger,&lt;br /&gt;    Local&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　對于一個具體例子來說：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 261px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.56%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Window.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type Button}&quot; x:Key=&quot;ButtonStyle&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;60&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;Style.Triggers&amp;gt;&lt;br /&gt;                &amp;lt;Trigger Property=&quot;IsMouseOver&quot; Value=&quot;True&quot;&amp;gt;&lt;br /&gt;                    &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;80&quot;/&amp;gt;&lt;br /&gt;                &amp;lt;/Trigger&amp;gt;&lt;br /&gt;            &amp;lt;/Style.Triggers&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;/Window.Resources&amp;gt;&lt;br /&gt;    &amp;lt;Grid&amp;gt;&lt;br /&gt;        &amp;lt;Button x:Name=&quot;button1&quot; Style=&quot;{StaticResource ButtonStyle}&quot; Background=&quot;{DynamicResource brush}&quot; Width=&quot;20&quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　第4行用Style的Setter設置Width=60，這個優先級是Style；第6行當IsMouseOver為True時設置Width=80，這個優先級是StyleTrigger；第13行使用Style的Button定義Width=20，這個優先級是Local。Local具有最高的優先級，所以即使鼠標移到Button上，第6行的Trigger也會因為優先級不夠高而不起作用。如果去掉了第13行中的Width=20，那麼鼠標移到Button上時Width會變為80，鼠標移開后會回到第4行的設置的60來。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Style &amp;amp; FrameworkElement&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　Style作為一個屬性定義在FrameworkElement上，所有繼承自FrameworkElement的控件都可以使用Style。FrameworkElement定義了多個Style：Style，ThemeStyle，FocusVisualStyle： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;FocusVisualStyle：是當控件獲得鍵盤焦點時，顯示在外面的一個虛線框，這個Style並沒有直接作用在對應的FrameworkElement上，而是當控件獲得鍵盤焦點時使用AdornLayer創建了一個新的Control，然后再這個Control上使用FocusVisualStyle，再把它遮蓋在對應的FrameworkElement上形成一個虛線框的效果。 &lt;br /&gt;&lt;li&gt;Style：就是我們前面一直設置的Style。 &lt;br /&gt;&lt;li&gt;ThemeStyle：這里引入了一個Theme的概念，具體來談一下它。&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　Windows定了很多Theme（主題），你可以在控制面板中切換Theme，如圖： &lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://images.cnblogs.com/cnblogs_com/Zhouyongh/201108/2011080111510875.png&quot;&gt;&lt;img title=&quot;Theme&quot; border=&quot;0&quot; alt=&quot;Theme&quot; src=&quot;http://images.cnblogs.com/cnblogs_com/Zhouyongh/201108/201108011151088057.png&quot; width=&quot;580&quot; height=&quot;415&quot;&gt;&lt;/a&gt; &lt;br /&gt;&lt;p&gt;　　最上面的兩排都屬于Aero主題，當從Aero主題切換到Windows Classic主題后，任務欄，窗口以及窗口內的控件外觀都會發生變化。為了更好的切換主題，WPF引入了ThemeStyle這個概念。當我們使用VS2010的模板生成一個自定義控件（Custom Control）后，會自動添加一個Themes的文件夾以及一個Generic.xaml的文件，如圖： &lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://images.cnblogs.com/cnblogs_com/Zhouyongh/201108/201108011151085549.png&quot;&gt;&lt;img title=&quot;generic&quot; border=&quot;0&quot; alt=&quot;generic&quot; src=&quot;http://images.cnblogs.com/cnblogs_com/Zhouyongh/201108/201108011151083041.png&quot; width=&quot;209&quot; height=&quot;55&quot;&gt;&lt;/a&gt; &lt;br /&gt;&lt;p&gt;　　這里的Aero.NormalColor.xaml是手動添加的，先略去不談，來談談控件（Control）的默認樣式。 &lt;br /&gt;&lt;p&gt;　　WPF默認提供了很多控件，Button，ListBox，TabControl等等，我們使用這些控件時，是沒有指定它的樣式（Style）的，WPF為我們提供了默認Style，這個默認Style是與Windows主題相關的。比如我們切換Windows的主題從Aero到Classic，WPF窗口里的控件外觀也會發生變化。這些默認的Style是以ResourceDictionary的形式保存在PresentationFramework.Aero.dll，PresentationFramework.Classic.dll等dll中的，這里的命名規則是：程序集名稱+Theme名稱+.dll。 &lt;br /&gt;&lt;p&gt;　　那麼WPF又是如何根据Windows的Theme找到對應的ThemeStyle呢？WPF提出了ThemeInfo這個Attribute來指定Theme信息。ThemeInfo一般定義在Properties/AssemblyInfo.cs中，如：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 97px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 97.7%; background-color: #eee&quot;&gt;&lt;code&gt;[assembly: ThemeInfo(&lt;br /&gt;    ResourceDictionaryLocation.SourceAssembly,&lt;br /&gt;    ResourceDictionaryLocation.SourceAssembly)&lt;br /&gt;)]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　ThemeInfo有兩個參數，第一個參數指的是ThemeResource，第二個參數指的是GenericResource，它們的類型是ResourceDictionaryLocation：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 114px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 97.67%; background-color: #eee&quot;&gt;&lt;code&gt;public enum ResourceDictionaryLocation&lt;br /&gt;{&lt;br /&gt;    None = 0,&lt;br /&gt;    SourceAssembly = 1,&lt;br /&gt;    ExternalAssembly = 2&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　ResourceDictionaryLocation的None指不存在對應的Resource，SourceAssembly指該程序集（Assembly）中存在對應的Resource，ExternalAssembly指對應的Resource保存在外部的程序集（Assembly）中，這個外部程序集的查找規則就是我們前面看到的：程序集名稱+Theme名稱+.dll。 &lt;br /&gt;&lt;p&gt;　　對于一個控件，無論是系統自帶的控件還是我們自定義的控件，WPF啟動時都會通過當前Windows系統的Theme查找它對應的ThemeStyle。這個查找規則是： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;先通過控件的類型（Type）找到它對應的程序集（Assembly），然后獲取程序集中的ThemeInfo，看看它的ThemeResource和GenericResource在哪里。如果ThemeResource的值不是None，系統會讀取到ThemeResource對應的ResourceDictionary，在這個ResourceDictionary中查找是否定義了TargetType={x:Type 控件類型}，如果有，把控件的ThemeStyle指定為這個Style。 &lt;br /&gt;&lt;li&gt;如果第一步的查找失敗，那麼GenericResource派上用場，Generic這個詞表示一般。WPF會查看ThemeInfo的第二個參數GenericResource來查找它的ThemeStyle，查找規則同第一步，如果查找成功，把這個Style指定為控件的ThemeStyle。&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　任意一個控件，如果不顯式指定它的Style，並且查不到默認的ThemeStyle，這個控件是沒有外觀的。為了編程方便，當我們使用VS添加自定義控件時，VS默認幫我們生成了Generic.xaml，如果我們希望自定義的控件也要支持系統的Theme變化，可以在Themes這個文件夾下加入對應的ResourceDictionary，比如上面的Aero.NormalColor.xaml，並且指定程序集ThemeInfo的第一個參數為SourceAssembly，表明該程序集支持系統Theme變化並且對應的資源文件在該程序集中。當然，ResourceDictionary一定要放在Themes文件夾下，因為WPF查找ResourceDictionary時使用的是類似：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 106px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 97.67%; background-color: #eee&quot;&gt;&lt;code&gt;string relativePackUriForResources = &quot;/&quot; +&lt;br /&gt;    themeAssemblyName.FullName +&lt;br /&gt;    &quot;;component/themes/&quot; +&lt;br /&gt;    themeName + &quot;.&quot; +&lt;br /&gt;    colorScheme + &quot;.xaml&quot;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;這樣的方法。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Style &amp;amp; ResourceDictionary&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　前面提到了很多次ResourceDictionary，關于WPF的Resource系統，以后再來細談。WPF的Resource系統使用ResourceDictionary來儲存Resource，ResourceDictionary，顧名思義，也是一個Dictionary，既然是Dictionary，就是按鍵/值對來存儲的。我們最前面在Window的Resource中創建Style時，指定了Style對應的鍵值（x:Key），后面又用StaticResource來引用這個鍵值。 &lt;br /&gt;&lt;p&gt;　　如果在ResourceDictionary中添加一個對象Button，不指定它的鍵值（x:Key），是不能通過編譯的。我們前面介紹的隱式（Implicit）Style，只指定了一個TargetType={x:Type&amp;nbsp; 類型}，並沒有指定鍵值，為什麼它可以通過編譯呢？ &lt;br /&gt;&lt;p&gt;　　對于在ResourceDictionary中添加Style，如果我們沒有指定鍵值（x:Key），WPF會默認幫我們生成鍵值，這個鍵值不是一個String，而是一個類型object（具體來說是Type實例），也就是說相當于：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 26px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 96.96%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Style TargetType=&quot;{x:Type Button}&quot; x:Key=&quot;{x:Type Button}&quot;&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;后面的x:Key可以省略掉。 &lt;br /&gt;&lt;p&gt;　　Appliation以及FrameworkElement類都定義了Resources屬性，內部都持有一個ResourceDictionary，Resource查找遵循的最基本原則是就近原則，如：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 342px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 100.14%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Window.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type Button}&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Yellow&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type ToggleButton}&quot; x:Key=&quot;toggleBtnStyle&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Red&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;/Window.Resources&amp;gt;&lt;br /&gt;    &amp;lt;StackPanel&amp;gt;&lt;br /&gt;        &amp;lt;StackPanel.Resources&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type Button}&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Blue&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type ToggleButton}&quot; x:Key=&quot;toggleBtnStyle&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Green&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;/StackPanel.Resources&amp;gt;&lt;br /&gt;        &amp;lt;ToggleButton Width=&quot;80&quot; Height=&quot;20&quot; Style=&quot;{DynamicResource toggleBtnStyle}&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;Button Width=&quot;80&quot; Height=&quot;20&quot;  Content=&quot;button2&quot; Click=&quot;Button_Click&quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　Window和StackPanel的Resources中都分別定義了toggleBtnStyle以及隱式Style（Button），根据就近原則，StackPanel內部的ToggleButton和Button會應用StackPanel的Resource而不會使用Window的。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;Style Merge&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　這里要提到本篇的重點也是不被人注意卻經常出錯的地方，Style的合並（Merge）。 &lt;br /&gt;&lt;p&gt;　　前面提到了很多Style，ThemeStyle，Style，隱式Style。我們提過，Style相當于一個屬性值的批處理，那麼對于一個屬性，只能有一個預設值而不能多個，這些Style在運行時要進行合並，然后作用在FrameworkElement上。 &lt;br /&gt;&lt;p&gt;　　Style的合並，要分兩步進行： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;找到所有Style。 &lt;br /&gt;&lt;li&gt;确定Style的優先級，根据優先級來合並Style。&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　以Button來說： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;如果當前Windows的Theme是Aero，啟動后會從PresentationFramework.Aero.dll中找到對應的ThemeStyle。 &lt;br /&gt;&lt;li&gt;如果在Button上使用StaticResource或者DynamicResource指定了Style，會通過鍵值在Resource系統中找到對應的Style。 &lt;br /&gt;&lt;li&gt;如果沒有在Button上顯式指定Style，會通過Resource系統查找隱式Style（x:Type Button）。 &lt;br /&gt;&lt;li&gt;第二步和第三步是排他的，這兩步只能确定一個Style，然后把這個Style和ThemeStyle進行合並（Merge）得到Button最終的效果。&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　先從合並來說，顯式或者隱式Style的優先級是高于ThemeStyle的，如果Style和ThemeStyle的Setter中都對同一屬性進行了預設，那麼會取Style里面的Setter而忽略ThemeStyle。這里比較特殊的是EventSetter，EventSetter使用的是RoutedEvent，如果兩個Style的EventSetter對同一個RoutedEvent進行了設置，兩個都會注冊到RoutedEvent上。 &lt;br /&gt;&lt;p&gt;　　前面看到，顯式和隱式Style是排他的，兩者只能取一，在實際項目中，在全局定義好Button的基本樣式，然后具體使用上再根据基本樣式做一些特殊處理，這種需求是很常見的。為了解決這種需求，Style提出了BasedOn屬性，來表示繼承關系，如：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 437px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 99.76%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Window&amp;gt;&lt;br /&gt;    &amp;lt;Window.Resources&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type Button}&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;80&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Height&quot; Value=&quot;20&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;EventSetter Event=&quot;Click&quot; Handler=&quot;btnBase_Click&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;Style TargetType=&quot;{x:Type ButtonBase}&quot; x:Key=&quot;toggleBtnStyle&quot;&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Width&quot; Value=&quot;80&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Height&quot; Value=&quot;20&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Red&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;/Window.Resources&amp;gt;&lt;br /&gt;    &amp;lt;StackPanel&amp;gt;&lt;br /&gt;        &amp;lt;StackPanel.Resources&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type Button}&quot; BasedOn=&quot;{StaticResource {x:Type Button}}&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Blue&quot;/&amp;gt;&lt;br /&gt;                &amp;lt;EventSetter Event=&quot;Click&quot; Handler=&quot;btn_Click&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;            &amp;lt;Style TargetType=&quot;{x:Type ToggleButton}&quot; x:Key=&quot;toggleBtnStyle&quot; BasedOn=&quot;{StaticResource toggleBtnStyle}&quot;&amp;gt;&lt;br /&gt;                &amp;lt;Setter Property=&quot;Background&quot; Value=&quot;Green&quot;/&amp;gt;&lt;br /&gt;            &amp;lt;/Style&amp;gt;&lt;br /&gt;        &amp;lt;/StackPanel.Resources&amp;gt;&lt;br /&gt;        &amp;lt;ToggleButton Style=&quot;{DynamicResource toggleBtnStyle}&quot;/&amp;gt;&lt;br /&gt;        &amp;lt;Button Content=&quot;button2&quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　為了更清晰的解釋，給出了一個不太常見的例子。第16行創建了一個隱式Style（Button），它的BasedOn屬性仍然是隱式Style（Button），Resource系統會向上查找找到Window的Resorces中的隱式Style（Button），然后把兩者合並。對于同一個ResourceDictionary，是不允許有重復鍵值的，StackPanel和Window各有各自的ResourceDictionary，他們的鍵值不受干擾，查找時會通過就近原則來找到優先級最高的Resource。第20行ToggleButton的例子和Button是一樣的，只是它查找到的第8行toggleBtnStyle的TargetStyle是ButtonBase，ButtonBase是ToggleButton的基類，BasedOn屬性也可以作用。 &lt;br /&gt;&lt;p&gt;　　WPF的Style机制是一個密封（Seal）机制，它的書寫方式很靈活，可以支持合並等，當最后合並后，Style就被密封（Seal），內部的Setter等不允許再被修改。這種密封的設計有它的道理，但在Style的動態性上就稍顯不足。 &lt;br /&gt;&lt;p&gt;　　以自定義控件為例，自定義一個Button，名字叫MyButton，它繼承自Button，在自定義控件中，經常可以看到這樣的代碼：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 82px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.02%; background-color: #eee&quot;&gt;&lt;code&gt;static MyButton()&lt;br /&gt;{&lt;br /&gt;    DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　這里出現了DefaultStyle，這個是WPF對ThemeStyle的另一個說法，ThemeStyle就是用來确定默認的Style的，后來包括BaseValueSource中也使用了DefaultStyle來表示ThemeStyle。在MyButton的靜態函數中重載DefaultStyleKeyProperty內部Metadata的含義是告訴WPF系統，查找MyButton的ThemeStyle使用的鍵值從{x:Type Button}被改成了{x:Type MyButton}。 &lt;br /&gt;&lt;p&gt;　　如果像上述代碼一樣修改了DefaultStyleKeyProperty，那麼需要我們在Themes/Generic.xaml中定義好MyButton的默認（Theme）Style，否則MyButton是沒有外觀的，因為查找ThemeStyle的鍵值已經被修改，PresentationFramework.Aero.dll等dll中是沒有定義{x:Type MyButton}的。 &lt;br /&gt;&lt;p&gt;　　前面是關于ThemeStyle的用法，那麼回到隱式Style上來，如果我們在Application的Resources中定義了Button的隱式Style（TargetType={x:Type Button}），即使沒有顯式設置MyButton的Style，所有的MyButton控件也不會使用這個隱式Style的。需要你在Application的Resources中，在定義Button隱式Style的下面定義&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 58px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 98.2%; background-color: #eee&quot;&gt;&lt;code&gt;&amp;lt;Style TargetType=&quot;{x:Type local:MyButton}&quot; BasedOn=&quot;{StaticResource {x:Type Button}}&quot;/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　這里就回到Style的合並（Merge）上來了，Style的Merge是很基本（很傻）的合並（Merge），它不具備Auto性。具體來說，就是： &lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;基類控件的隱式Style不會作用到派生類控件上。 &lt;br /&gt;&lt;li&gt;像前面在Window和StackPanel中分別定義了隱式Style（Button），這兩個隱式Style不會智能合並后再作用到Button上，而是通過就近原則只選其一。 &lt;br /&gt;&lt;li&gt;Style的BasedOn屬性只支持StaticResource方式引用，因為Style繼承自DispatcherObject而不是DependencyObject，DynamicResource只支持DP。&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;　　這些問題都需要通過Style的BasedOn來解決，因為BasedOn用的是靜態引用（StaticResource），當隱式Style發生變化時就有麻煩了。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;換膚&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　UI程序的換膚是很炫的玩意，換膚分兩種：1，更換整個控件的Style；2，更換Style中的顏色畫刷（Brush）。后者的實現很簡單，定義好顏色畫刷的資源文件（ResourceDictionary），使用畫刷的時候使用DynamicResource綁定，換膚的時候替換畫刷的資源文件就可以了。 &lt;br /&gt;&lt;p&gt;　　很多公司都有自己皮膚庫，這些皮膚庫一般都是隱式的Style，定義了所有控件的隱式Style，使用時把這個皮膚資源Merge到Application的Resources中。換膚時把舊的皮膚資源從Application的Resources中刪除，替換成新的皮膚資源ResourceDictionary。 &lt;br /&gt;&lt;p&gt;　　這種做法很好理解，但是碰到Style的BasedOn屬性就不起作用了，BasedOn屬性使用是StaticResource，是靜態的一次性的。新的皮膚庫被添加到Application資源文件后，如果在Application的資源文件中已經定義過&amp;lt;Style TargetType=“{x:Type Button}” BasedOn=“{StaticResource {x:Type Button}}”/&amp;gt;這樣隱式的Style，控件是不會更新皮膚的。如果有這方面的需求，需要手動合並（Merge）Style來解決問題，類似：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 273px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 97.48%; background-color: #eee&quot;&gt;&lt;code&gt;public static void Merge(this Style style, Style otherStyle)&lt;br /&gt;{&lt;br /&gt;    foreach (SetterBase currentSetter in otherStyle.Setters)&lt;br /&gt;    {&lt;br /&gt;        style.Setters.Add(currentSetter);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    foreach (TriggerBase currentTrigger in otherStyle.Triggers)&lt;br /&gt;    {&lt;br /&gt;        style.Triggers.Add(currentTrigger);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    foreach (object key in otherStyle.Resources.Keys)&lt;br /&gt;    {&lt;br /&gt;        style.Resources[key] = otherStyle.Resources[key];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　這里還需要加上一些條件判斷，以及決定是否要遞歸合並otherStyle的BasedOn，回到前面，程序需要使用DynamicResource來監听Application資源中隱式Style的變化，用一個附加屬性來解決：&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 468px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 97.3%; background-color: #eee&quot;&gt;&lt;code&gt;public static readonly DependencyProperty AutoMergeStyleProperty =&lt;br /&gt;    DependencyProperty.RegisterAttached(&quot;AutoMergeStyle&quot;, typeof(Type), typeof(Behavior),&lt;br /&gt;    new FrameworkPropertyMetadata((Type)null,&lt;br /&gt;    new PropertyChangedCallback(OnAutoMergeStyleChanged)));&lt;br /&gt;    &lt;br /&gt;private static void OnAutoMergeStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&lt;br /&gt;{&lt;br /&gt;    if (e.OldValue == e.NewValue)&lt;br /&gt;    {&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    FrameworkElement control = d as FrameworkElement;&lt;br /&gt;    if (control == null)&lt;br /&gt;    {&lt;br /&gt;        throw new NotSupportedException(&quot;AutoMergeStyle can only used in FrameworkElement&quot;);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    Type type = e.NewValue as Type;&lt;br /&gt;    if (type != null)&lt;br /&gt;    {&lt;br /&gt;        control.SetResourceReference(Behavior.BaseOnStyleProperty, type);&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        control.ClearValue(Behavior.BaseOnStyleProperty);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;　　SetResourceReference是XAML中DynamicResource的代碼表示，相當于Behavior.BaseOnStyle={DynamicResource type}。對控件使用SetResourceReference，監听的鍵值是type，監听的屬性是一個我們自定義的附加屬性BaseOnStyleProperty。當換膚替換Application的資源文件時，BaseOnStyle屬性被更新，在BaseOnStyleProperty的Changed事件中可以讀取控件的Style屬性和新的ThemeStyle，調用Merge方法Merge兩者然后再設置到控件的Style屬性上。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;總結&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　WPF中Style的設計中規中矩，把UI對象樣式和結构分離是它的最初想法，其中也加入了Trigger等一些好的設計，但在使用中還是會出現一些問題，它本身也不是那麼智能完美。希望朋友們都能從內到外的看待Style，更好的玩轉它。 &lt;br /&gt;&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;&lt;br /&gt;&lt;h3&gt;閑話&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;　　這個深入WPF系列也寫了好几篇了，比起用嘴上白話一通，寫文章需要更多的耐心和細致。講解有很多境界：把簡單的東西講復雜；把復雜的東西講復雜；把復雜的東西講簡單；把復雜的東西講簡單，而且還有詩情哲理。我達不到那麼高的境界，希望能做到直接不回避的把技朮主線講清楚，也希望能更多的听到朋友們的反饋，我會繼續補充，爭取把這個系列寫好。 &lt;br /&gt;&lt;p&gt;　　謝謝支持，謝謝您頂一下。　^_^ &lt;br /&gt;&lt;p&gt;作者：&lt;a href=&quot;http://www.cnblogs.com/Zhouyongh&quot;&gt;周永恆&lt;/a&gt;&lt;br&gt;出處：&lt;a href=&quot;http://www.cnblogs.com/Zhouyongh&quot;&gt;http://www.cnblogs.com/Zhouyongh&lt;/a&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/5179589113517004777/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-style.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/5179589113517004777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/5179589113517004777'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-style.html' title='WPF - 深入 Style'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-240939586954544615</id><published>2013-06-03T10:07:00.001+08:00</published><updated>2013-06-03T10:07:43.013+08:00</updated><title type='text'>WPF – 使用 DrawingVisual 描繪圖形</title><content type='html'>&lt;p&gt;在 WPF 中有很多種方式來描繪圖形, 其 DrawingVisual 是一個輕量級的 Class, 它需一個 container 來承接, 並不提供 Layout, Hit-Testing 及 Event-Handling.&lt;/p&gt; &lt;p&gt;那來實作一下如何使用 DrawingVisual 來描繪圖形. &lt;/p&gt; &lt;p&gt;建立一個 class, 它繼承 FrameworkElement Class, 並描繪一個 Rectangle .&lt;br&gt;&lt;/p&gt;&lt;pre style=&quot;overflow: auto; font-size: 12px; border-top: #999999 1px dashed; height: 535px; font-family: andale mono, lucida console, monaco, fixed, monospace; border-right: #999999 1px dashed; border-bottom: #999999 1px dashed; color: #000000; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; border-left: #999999 1px dashed; line-height: 14px; padding-right: 5px; width: 94.97%; background-color: #eee&quot;&gt;&lt;code&gt;    public class MyVisualHost : FrameworkElement&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        private VisualCollection childern;&lt;br /&gt;&lt;br /&gt;        public MyVisualHost() {&lt;br /&gt;            childern = new VisualCollection(this);&lt;br /&gt;            childern.Add(CreateDrawingVisualRectangle());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        protected override int VisualChildrenCount&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return childern.Count;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        protected override Visual GetVisualChild(int index)&lt;br /&gt;        {&lt;br /&gt;            return childern[index];&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private DrawingVisual CreateDrawingVisualRectangle()&lt;br /&gt;        {&lt;br /&gt;            DrawingVisual drawing = new DrawingVisual();&lt;br /&gt;            using (DrawingContext content = drawing.RenderOpen())&lt;br /&gt;            {&lt;br /&gt;                content.DrawRectangle(Brushes.Red, new Pen(Brushes.Blue, 3), new Rect(new Point(100, 100), new Size(30, 30)));&lt;br /&gt;                content.Close();&lt;br /&gt;            }&lt;br /&gt;            return drawing;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;結果如下所示 : &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpfhnpo7YGKpum85QUWR_o2lCs3hykIlv-vGZcj2pQuaEXK34WUiJIBLvUEXwDd06dxIp5bbt5wbGP-O4Ew0oT8qZa7B659vuckQ3cwAJ9Ul_2TMC8VrgaqCeUxmypUY8M9ZxReTYJgQc/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_Wa1dsx16_ZJah-4Xy3F90LRvVrKvVTAmoZ36lFtgvPSNK2laqQdhrKFjBza5CHrRzULt3nOKN9oJLQM2orOPddxyjPlOVLvha6WogFGRLzGF3lXVR67LZ5uWxBUuU8he3N1_KXvOAgA//?imgmax=800&quot; width=&quot;378&quot; height=&quot;359&quot;&gt;&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/240939586954544615/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-drawingvisual.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/240939586954544615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/240939586954544615'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/06/wpf-drawingvisual.html' title='WPF – 使用 DrawingVisual 描繪圖形'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_Wa1dsx16_ZJah-4Xy3F90LRvVrKvVTAmoZ36lFtgvPSNK2laqQdhrKFjBza5CHrRzULt3nOKN9oJLQM2orOPddxyjPlOVLvha6WogFGRLzGF3lXVR67LZ5uWxBUuU8he3N1_KXvOAgA/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-624977726198380766</id><published>2013-05-31T10:53:00.001+08:00</published><updated>2013-05-31T10:53:22.425+08:00</updated><title type='text'>WPF - 性能優化</title><content type='html'>&lt;p&gt;&amp;nbsp; &lt;ul&gt; &lt;li&gt;WPF性能優化一 - Rendering Tier&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;根据硬件配置的不同，WPF采用不同的Rendering Tier做渲染。下列情況請特別注意，因為在這些情況下，即使是處于Rendering Tier 2的情況下也不會硬件加速。(不全，其余請查閱SDK)&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化二 - 布局和設計&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;盡量多使用Canvas等簡單的布局元素，少使用Grid或者StackPanel等復雜的，越復雜性能開銷越大。&amp;nbsp; &lt;/li&gt; &lt;li&gt;建立邏輯樹或者視覺樹的時候，遵循Top-Down的原則。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化三 - 圖像&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;對Image做動畫處理的時候（如調整大小等），可以使用這條語句RenderOptions.SetBitmapScalingMode(MyImage,BitmapScalingMode.LowQuality)，以改善性能。 &lt;/li&gt; &lt;li&gt;用TileBrush的時候，可以CachingHint。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化四 - 對象行為&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;訪問CLR對象和CLR屬性的效率會比訪問DependencyObject/DependencyProperty高。注意這里指的是訪問，不要和前面的綁定混淆了。但是，把屬性注冊為DependencyProperty會有很多的優點：比如繼承、數据綁定和Style。 &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化五 - 應用程序資源&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;在自定義控件，盡量不要在控件的ResourceDictionary定義資源，而應該放在Window或者Application級。因為放在控件中會使每個實例都保留一份資源的拷貝。 &lt;/li&gt; &lt;li&gt;盡量使用Static Resources,但不能盲目使用。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化六 - 文本&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;文字少的時候用TextBlock或者label,長的時候用FlowDocument.&amp;nbsp; &lt;/li&gt; &lt;li&gt;使用元素TextFlow和TextBlock時，如果不需要TextFlow的某些特性，就應該考慮使用TextBlock，因為它的效率更高。&amp;nbsp; &lt;/li&gt; &lt;li&gt;在TextFlow中使用UIElement（比如TextBlock）所需的代价要比使用TextElement（比如Run）的代价高.在FlowDocument中盡量避免使用TextBlock，要用Run替代。 &lt;/li&gt; &lt;li&gt;在TextBlock中顯式的使用Run命令比不使用Run命名的代碼要高。&lt;/li&gt; &lt;li&gt;把Label（標簽）元素的ContentProperty和一個字符串（String）綁定的效率要比把字符串和TextBlock的Text屬性綁定的效率低。因為Label在更新字符串是會丟棄原來的字符串，全部重新顯示內容。如果字符串不需要更新，用Label就無所謂性能問題。 &lt;/li&gt; &lt;li&gt;在TextBlock塊使用HyperLinks時，把多個HyperLinks組合在一起效率會更高。&lt;/li&gt; &lt;li&gt; 顯示超鏈接的時候，盡量只在IsMouseOver為True的時候顯示下划線，一直顯示下划線的代碼高很多&amp;nbsp; &lt;/li&gt; &lt;li&gt;盡量不使用不必要的字符串連接。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化七 - 數据綁定&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;在使用數据綁定的過程中，如果綁定的數据源是一個CLR對象，屬性也是一個CLR屬性，那麼在綁定的時候對象CLR對象所實現的机制不同，綁定的效率也不同。&lt;/li&gt; &lt;ol&gt; &lt;li&gt;數据源是一個CLR對象，屬性也是一個CLR屬性。對象通過TypeDescriptor/PropertyChanged模式實現通知功能。此時綁定引擎用TypeDescriptor來反射源對象。效率最低。 &lt;/li&gt; &lt;li&gt;數据源是一個CLR對象，屬性也是一個CLR屬性。對象通過INotifyPropertyChanged實現通知功能。此時綁定引擎直接反射源對象。效率稍微提高。&lt;/li&gt; &lt;li&gt;數据源是一個DependencyObject，而且屬性是一個DependencyProperty。此時不需要反射，直接綁定。效率最高。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt; &lt;li&gt;當一個CLR對象很大時，比如有1000個屬性時，盡量把這個對象分解成很多很小的CLR對象。比如分成1000個只有一個屬性的CLR對象。&amp;nbsp; &lt;/li&gt; &lt;li&gt;&lt;br&gt;當我們在列表（比如ListBox）顯示了一個CLR對象列表（比如List）時，如果想在修改List對象后，ListBox也動態的反映這種變化。此時，我們應該使用動態的ObservableCollection對象綁定。而不是直接的更新ItemSource。兩者的區別在于直接更新ItemSource會使WPF拋棄ListBox已有的所有數据，然后全部重新從List加載。而使用ObservableCollection可以避免這種先全部刪除再重載的過程，效率更高。 &lt;/li&gt; &lt;li&gt;盡量綁定IList而不是IEnumerable到ItemsControl。&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt; &lt;ul&gt; &lt;li&gt;WPF性能優化八 - 其它性能建議&amp;nbsp; &lt;/li&gt;&lt;/ul&gt; &lt;ol&gt; &lt;ol&gt; &lt;li&gt;如果需要修改元素的Opacity屬性，最后修改一個Brush的屬性，然后用這個Brush來填充元素。&lt;/li&gt; &lt;li&gt;用NavigationWindow的時候，盡量Update the client area by object,而不是URI&amp;nbsp; &lt;/li&gt; &lt;li&gt;盡量不要使用ScrollBarVisibility=Auto&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/624977726198380766/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/05/wpf.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/624977726198380766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/624977726198380766'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/05/wpf.html' title='WPF - 性能優化'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-8586762814923578045</id><published>2013-05-14T14:42:00.001+08:00</published><updated>2013-05-14T14:42:25.015+08:00</updated><title type='text'>C# - NHibernate Queries Examples (轉貼)</title><content type='html'>&lt;p&gt;Today was the first day of my NHibernate course, and I think that it might be good to point out a few of the samples that we worked with. Those are pretty basic NHibernate queries, but they are probably going to be useful for beginners. &lt;p&gt;Let us take my usual Blog model, and see what kind of queries (and results) we can come up with: &lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_2.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb.png&quot; width=&quot;541&quot; height=&quot;399&quot;&gt;&lt;/a&gt; &lt;p&gt;Let us find a blog by its identifier: &lt;blockquote&gt;&lt;pre&gt;var blog = s.Get&amp;lt;Blog&amp;gt;(1);&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which results in:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_4.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_1.png&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;We can also try:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;var blog = s.Load&amp;lt;Blog&amp;gt;(1);&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which would result in… absolutely no SQL queries. You can look at a more deep discussion of that &lt;a href=&quot;http://ayende.com/Blog/archive/2009/04/30/nhibernate-ndash-the-difference-between-get-load-and-querying-by.aspx&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;Now, let us try to search by a property:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(Restrictions.Eq(&quot;Title&quot;, &quot;Ayende @ Rahien&quot;))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;Which results in:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_6.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_2.png&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;If we try to make the same with HQL, it would look:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b where b.Title = :title&quot;)&lt;br&gt;    .SetParameter(&quot;title&quot;,&quot;Ayende @ Rahien&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which results in slight different SQL than using the criteria:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_8.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_3.png&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;What about trying a more complex conditional? Let us try to see comparing two properties:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(Restrictions.Eq(&quot;Title&quot;,&quot;Ayende @ Rahien&quot;))&lt;br&gt;    .Add(Restrictions.Eq(&quot;Subtitle&quot;, &quot;Send me a patch for that&quot;))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which results in:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_10.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_4.png&quot; width=&quot;450&quot; height=&quot;171&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Let us do that again, but using two properties using an OR:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(Restrictions.Disjunction()&lt;br&gt;             .Add(Restrictions.Eq(&quot;Title&quot;, &quot;Ayende @ Rahien&quot;))&lt;br&gt;             .Add(Restrictions.Eq(&quot;Subtitle&quot;, &quot;Send me a patch for that&quot;)))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which would result in:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_12.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_5.png&quot; width=&quot;464&quot; height=&quot;169&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;We can also execute the same SQL using the following syntax:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(&lt;br&gt;            Restrictions.Eq(&quot;Title&quot;, &quot;Ayende @ Rahien&quot;) || &lt;br&gt;            Restrictions.Eq(&quot;Subtitle&quot;, &quot;Send me a patch for that&quot;)&lt;br&gt;        )&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Doing the same using HQL would be:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b where b.Title = :title and b.Subtitle = :subtitle&quot;)&lt;br&gt;    .SetParameter(&quot;title&quot;,&quot;Ayende @ Rahien&quot;)&lt;br&gt;    .SetParameter(&quot;subtitle&quot;, &quot;Send me a patch for that&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which results in:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_14.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_6.png&quot; width=&quot;472&quot; height=&quot;172&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;And changing that to an OR is pretty self explanatory :-)&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b where b.Title = :title &lt;strong&gt;or&lt;/strong&gt; b.Subtitle = :subtitle&quot;)&lt;br&gt;    .SetParameter(&quot;title&quot;,&quot;Ayende @ Rahien&quot;)&lt;br&gt;    .SetParameter(&quot;subtitle&quot;, &quot;Send me a patch for that&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Giving us:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_16.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_7.png&quot; width=&quot;467&quot; height=&quot;169&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Let us try something a bit more complex, finding a blog by a post title:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .CreateCriteria(&quot;Posts&quot;)&lt;br&gt;    .Add(Restrictions.Eq(&quot;Title&quot;,&quot;NHibernate Rocks&quot;))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;That gives us:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_18.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_8.png&quot; width=&quot;371&quot; height=&quot;266&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;You will note that we force a load of the Posts collection. We can try something else, though:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(Subqueries.PropertyIn(&quot;id&quot;,&lt;br&gt;        DetachedCriteria.For&amp;lt;Post&amp;gt;()&lt;br&gt;            .Add(Restrictions.Eq(&quot;Title&quot;,&quot;NHibernate Rocks&quot;))&lt;br&gt;            .SetProjection(Projections.Property(&quot;Blog.id&quot;))&lt;br&gt;        ))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which would give us the same result, but without loading the Posts collection:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_20.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_9.png&quot; width=&quot;511&quot; height=&quot;184&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;This is a pretty common example of changing the way that we compute complex conditionals when we want to avoid wide result sets.&lt;br /&gt;&lt;p&gt;Let us do the same with HQL:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b join b.Posts p where p.Title = :title&quot;)&lt;br&gt;    .SetParameter(&quot;title&quot;, &quot;NHibernate Rocks&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Which would result:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_22.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_10.png&quot; width=&quot;383&quot; height=&quot;272&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;We have the same issue as with the first Criteria API, and we can resolve it in the same way:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b where b.id in (from Post p where p.Title = :title)&quot;)&lt;br&gt;    .SetParameter(&quot;title&quot;, &quot;NHibernate Rocks&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;And the same result as in the Criteria API show us:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_24.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_11.png&quot; width=&quot;537&quot; height=&quot;187&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;And the final test, let us try to find a blog that has a post posted by a specific user:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateCriteria&amp;lt;Blog&amp;gt;()&lt;br&gt;    .Add(Subqueries.PropertyIn(&quot;id&quot;,&lt;br&gt;        DetachedCriteria.For&amp;lt;Post&amp;gt;()&lt;br&gt;            .SetProjection(Projections.Property(&quot;Blog.id&quot;))&lt;br&gt;            .CreateCriteria(&quot;User&quot;)&lt;br&gt;            .Add(Restrictions.Eq(&quot;Username&quot;,&quot;Ayende&quot;))&lt;br&gt;        ))&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;And this give us:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_26.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_12.png&quot; width=&quot;459&quot; height=&quot;213&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;The same thing with HQL will give us:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;var blogs = s.CreateQuery(&quot;from Blog b where b.id in (from Post p where p.User.Username = :user)&quot;)&lt;br&gt;    .SetParameter(&quot;user&quot;,&quot;Ayende&quot;)&lt;br&gt;    .List&amp;lt;Blog&amp;gt;();&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;p&gt;And that results:&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_28.png&quot;&gt;&lt;img title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/NHibernateQueriesExamples_13C29/image_thumb_13.png&quot; width=&quot;473&quot; height=&quot;211&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;來源 : &lt;a title=&quot;http://ayende.com/blog/4023/nhibernate-queries-examples&quot; href=&quot;http://ayende.com/blog/4023/nhibernate-queries-examples&quot;&gt;http://ayende.com/blog/4023/nhibernate-queries-examples&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/8586762814923578045/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/05/c-nhibernate-queries-examples.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/8586762814923578045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/8586762814923578045'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/05/c-nhibernate-queries-examples.html' title='C# - NHibernate Queries Examples (轉貼)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-3250749630614989402</id><published>2013-02-25T15:06:00.001+08:00</published><updated>2013-02-25T15:06:38.903+08:00</updated><title type='text'>Flex – Cairngorm 之初體驗</title><content type='html'>&lt;p&gt;最近在看 Flex 的 Framework, 以 Adobe 官方建議的 Cairngorm 做為開始.&lt;/p&gt; &lt;h6&gt;1. ModelLocator : &lt;/h6&gt; &lt;blockquote&gt; &lt;p&gt;此部份提供了 Model 的功能, 使用Signleton design pattern 的設計把所有的資料都收集到這邊.&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3_oWB0wHq6RJmYz0cUXqt6ZROdPEei-4ASD3_C_F8wBvPQe5_UBo0WgPgTcyIMAxRF59_P9dJIOMv2O1c9_m7Jyncd5U8xE2kBIFZTeytyzmrE0jA-PLSDtIoVPrC9sajVfFtqy_Yoi8/s1600-h/image%25255B4%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL9dO88z2HFtJsHKIUTrM_6GkaHLj56GiTfHP2gD95m3nAihUVIKM7bSuIwnl4EHNu_XfB-3YtZ9Ny98YXukJlp4CRRpoUZXfctuiOA4h8VCkMmTuhG_5F-ePCS3OwXi_u4LMq05rEQno//?imgmax=800&quot; width=&quot;479&quot; height=&quot;235&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;h6&gt;2. Command, Event, FrontController:&lt;/h6&gt; &lt;blockquote&gt; &lt;p&gt;在 Front Controller 註冊 Command&amp;nbsp; 與對應的 Event, Event Dispatcher 監聽 Event, 爾後操作過程中 dispatch event 觸發 Command 執行動作, 最後 Update Model 更新 View 顯示.&lt;/p&gt;&lt;/blockquote&gt; &lt;h6&gt;3. Interact with a server :&lt;/h6&gt; &lt;blockquote&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;ServiceLocator&lt;/strong&gt; : 此 Class 提供了 application 將使用的所有 services, 它包含了 HTTPService, WebService, RemoteObject 呼叫.&lt;br&gt; &lt;li&gt;&lt;strong&gt;Business Delegate&lt;/strong&gt; : 此 Class 有三個 Function&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; to locate the service that is needed&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; to call a method on the service&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; to route the result to the specified responder&lt;br&gt; &lt;li&gt;&lt;strong&gt;Value Object&lt;/strong&gt; : 此 Class 一般定義 property 並不需要任何的 methods, 使用來跟 Server 做 transfer strongly-typed complex data object.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHhzpnX4n0Blk57-Ae3y9EbqMiM7e6DgMh_NzZMHJGWEb7-rubj6DxDknYkkgqwSePdR8S5KsIfAuUKB7rZjx7xGJfDWWXm10_C3Yr16eUM1D9FhQvZE2OTBW0UU1Xxhlkm_VHMgIOuyg/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0Lry1SqtHl5Os-J-FMamsP8W9eNgMi39oB8L-5VnH-Vg4OvepDfzOhsPn7dYRlVywXlOG47RqMRMe4ZGYFMis6DLRrFB1_tKeu8QKrv-bgCu7pRADBdOizxbcJHlLBFJXkW_tYocbxeI//?imgmax=800&quot; width=&quot;470&quot; height=&quot;280&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;h6&gt;4. Responders, Commands, Delegates :&lt;/h6&gt; &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Responders&lt;/strong&gt; : Responders should deal only in strongly-typed application objects. Responders may set values on the model.&lt;br&gt;&lt;strong&gt;&lt;/strong&gt; &lt;li&gt;&lt;strong&gt;Commands&lt;/strong&gt; : Commands never deal directly with server interaction.Commands may set values on the model.&lt;br&gt; &lt;li&gt;&lt;strong&gt;Delegates&lt;/strong&gt; : Delegates should pass strongly typed strongly-typed application objects to the Responder. If the Delegate don’t receive strongly-styped application objects, it must parse and convert the data into that format.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCtbBfDYf8ycfgH5jmNgbD8zysVJuOh43vlHSM_K3do7jpUm0mvvQVaS9O2HYEcZT2JTSEIcECQIW41YiMKmSBDwPwuEzz21tgk-QdDw8miTXGhtVSazGhX0Iel3QOBwlZHVM3kqw7bs8/s1600-h/image15.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJkx4JdFBzR_1PoNQW-2HpI8-AhAVwWfC6h4Ua9N9mi7qEPr93FBtf9eez7GKaGVxn8t8XnfgMOMTPQmt3txAaBQvEC0IonDQe6z3RRLF-9SZ7V9baZimLrSpB7FHzohYEOR2masj5tVA//?imgmax=800&quot; width=&quot;518&quot; height=&quot;366&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Reference : &lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;http://archive.davidtucker.net/2007/10/07/getting-started-with-cairngorm-%e2%80%93-part-1/#&quot; target=&quot;_blank&quot;&gt;Getting Started with Cairngorm – Part 1&lt;/a&gt;&amp;nbsp; &lt;li&gt;&lt;a href=&quot;http://archive.davidtucker.net/2007/10/18/cairngorm-part-2/#&quot; target=&quot;_blank&quot;&gt;Getting Started with Cairngorm – Part 2&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://archive.davidtucker.net/2007/10/29/cairngorm-part-3/#&quot; target=&quot;_blank&quot;&gt;Getting Started with Cairngorm – Part 3&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://archive.davidtucker.net/2007/11/07/cairngorm-part-4/#&quot; target=&quot;_blank&quot;&gt;Getting Started with Cairngorm – Part 4&lt;/a&gt;  &lt;li&gt;&lt;a href=&quot;http://archive.davidtucker.net/2007/11/30/getting-started-with-cairngorm-%e2%80%93-part-5/#&quot; target=&quot;_blank&quot;&gt;Getting Started with Cairngorm – Part 5&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/3250749630614989402/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/02/flex-cairngorm.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3250749630614989402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3250749630614989402'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/02/flex-cairngorm.html' title='Flex – Cairngorm 之初體驗'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL9dO88z2HFtJsHKIUTrM_6GkaHLj56GiTfHP2gD95m3nAihUVIKM7bSuIwnl4EHNu_XfB-3YtZ9Ny98YXukJlp4CRRpoUZXfctuiOA4h8VCkMmTuhG_5F-ePCS3OwXi_u4LMq05rEQno/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-8957872991291226574</id><published>2013-02-21T13:44:00.001+08:00</published><updated>2013-02-21T13:44:30.031+08:00</updated><title type='text'>C# – 得知 Server 上 Protocol 是否已開啟</title><content type='html'>&lt;p&gt;當程式要得知 Server 上的 Protocol 是否已開啟, 可以試著去連接來查看, 下面的程式碼即可得知 Server 上其 Protocol 是否已開啟.下面提供一個簡單的範例.&lt;/p&gt;&lt;pre style=&quot;border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 97.57%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; height: 279px; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px&quot;&gt;&lt;code&gt;            TcpClient client = new TcpClient();&lt;br /&gt;            bool isPortExist = false;&lt;br /&gt;            Random rnd = new Random();&lt;br /&gt;            int portId = rnd.Next(10000, 60000);&lt;br /&gt;            &lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                client.Connect(&quot;localhost&quot;, portId);&lt;br /&gt;                isPortExist = true;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                isPortExist = false;&lt;br /&gt;            }&lt;br /&gt;            finally {&lt;br /&gt;                Console.WriteLine(string.Format(&quot;Port Id : {0},protocol  {1}&quot;, portId, isPortExist ? &quot;opened.&quot; : &quot;closed.&quot;));&lt;br /&gt;            }&lt;br /&gt;            Console.Read();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/8957872991291226574/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/02/c-server-protocol.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/8957872991291226574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/8957872991291226574'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/02/c-server-protocol.html' title='C# – 得知 Server 上 Protocol 是否已開啟'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-6153192277764732935</id><published>2013-02-01T10:02:00.001+08:00</published><updated>2013-02-01T10:02:00.808+08:00</updated><title type='text'>WPF - 窺探 Flow Diagram Designer 的設計</title><content type='html'>&lt;p&gt;最近收到一個很好玩的 Requirement，提供 Data Sources, Charts, Filters 等組件可讓 User 隨意組合這些元件為一個 Flow 並執行取得結果, 這讓我回想到三年前 WPF 出來時在網路上看到有好心人士提供了其作法和 Source Code, 想不到現在有這 Requirement 需要它了, 真的是太感謝這些好心人士了，那在此記錄一下這些相關的文章, 以防之後還有類似的需求時, 好方便瀏覽.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part-1&quot; target=&quot;_blank&quot;&gt;Part 1 – Drag, resize and rotate items on a canvas&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/23265/WPF-Diagram-Designer-Part-2&quot; target=&quot;_blank&quot;&gt;Part 2 – Toolbox, drag &amp;amp; drop, rubberband selection&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/23871/WPF-Diagram-Designer-Part-3&quot; target=&quot;_blank&quot;&gt;Part 3 – Connecting items&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;http://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part-4&quot; target=&quot;_blank&quot;&gt;Part 4 – Open/Save, Cut/Copy/Past/Delete and print&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/6153192277764732935/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/01/wpf-flow-diagram-designer.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6153192277764732935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6153192277764732935'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/01/wpf-flow-diagram-designer.html' title='WPF - 窺探 Flow Diagram Designer 的設計'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-6588523406871078867</id><published>2013-02-01T09:12:00.001+08:00</published><updated>2013-02-01T09:12:24.868+08:00</updated><title type='text'>Javascript – easy UI 的 datetimebox 自定日期時間格式</title><content type='html'>&lt;p&gt;在做 Web 的 UI 時, 其 easyUI 這個免費的 Javascript Framework 提供了很多好用的組件,來幫助我們建立豐富及美觀的 Web 畫面, 在日期組件中提供了 datebox, datetimebox 這二種組件, 並提供相對映的 member 讓我們可以自定日期(日期時間)格式, 提供一個 &lt;font color=&quot;#ff0000&quot;&gt;&lt;strong&gt;yyyy-MM-dd HH:mm: ss&lt;/strong&gt;&lt;/font&gt; 的時間格式&lt;/p&gt;&lt;pre style=&quot;border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 99.82%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; height: 207px; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px&quot;&gt;&lt;code&gt;    $(&quot;#startDate, #endDate&quot;).datetimebox({&lt;br /&gt;        formatter: function (date) {&lt;br /&gt;            return date.getFullYear()&lt;br /&gt;                + &quot;-&quot; + (date.getMonth() + 1).toString().leftPad(&quot;0&quot;, 2)&lt;br /&gt;                + &quot;-&quot; + date.getDate().toString().leftPad(&quot;0&quot;, 2)&lt;br /&gt;                + &quot; &quot; + date.getHours().toString().leftPad(&quot;0&quot;, 2)&lt;br /&gt;                + &quot;:&quot; + date.getMinutes().toString().leftPad(&quot;0&quot;, 2)&lt;br /&gt;                + &quot;:&quot; + date.getSeconds().toString().leftPad(&quot;0&quot;, 2);&lt;br /&gt;        },&lt;br /&gt;        parser: function (date) {&lt;br /&gt;            return new Date(Date.parse(date.replace(/-/g, &quot;/&quot;))); &lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;其顯示如下所示：&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg37CqLNbLV3eRLELTfaj8nCPOHmTf1JCTwRCXuoTCzPJAwNTsCeDCDhdp0-zitdEQeJuri8ATBYnaHCpAxy8e7M2p9yHKEnGNQrX-taQP-7gS3IPz3JVMzcNu_ZNgppcT6kelDN-3oQ8o/s1600-h/image3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Pg2SL-WhguC82g9DhLk-VYbFrZmHR0N-TYTuWOmskM0KG1HhePh-nAB9B0Fk5Bd10xtfXG9aC77eoxhjtk2S5dT-dl7V3ShSK1G1_iYJd8hKTuTLs_33MWr6T8P1WwgaOh1qU36gfYo//?imgmax=800&quot; width=&quot;584&quot; height=&quot;60&quot;&gt;&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/6588523406871078867/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/01/javascript-easy-ui-datetimebox.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6588523406871078867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/6588523406871078867'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/01/javascript-easy-ui-datetimebox.html' title='Javascript – easy UI 的 datetimebox 自定日期時間格式'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Pg2SL-WhguC82g9DhLk-VYbFrZmHR0N-TYTuWOmskM0KG1HhePh-nAB9B0Fk5Bd10xtfXG9aC77eoxhjtk2S5dT-dl7V3ShSK1G1_iYJd8hKTuTLs_33MWr6T8P1WwgaOh1qU36gfYo/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-4857947839437275197</id><published>2013-01-31T17:51:00.001+08:00</published><updated>2013-01-31T17:51:26.485+08:00</updated><title type='text'>C# – M$ Chart Control 自定 ToolTip 的顯示</title><content type='html'>&lt;p&gt;在使用 M$ Chart Control 來顯示 Chart 時, 一般的 Requirments 其 ToolTip 在顯示一般都為 X/Y Value，可是當有特別的資料需顯示時，那又該如何呢？在其 DataPoint Class 中提供一個SetCustomProperty Member 讓 User 可以設定其 Custom Property Value，那只需在 Series Class 中設定 ToolTipProperty 後，其 ToolTip 即可顯示 Custom Property.&lt;/p&gt;&lt;pre style=&quot;border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 99.82%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; height: 153px; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px&quot;&gt;&lt;code&gt;    Series s = new Series();&lt;br /&gt;    s.Name = &quot;SeriesName&quot;;&lt;br /&gt;    s.ChartType = SeriesChartType.Line;&lt;br /&gt;    s.MarkerStyle = MarkerStyle.Circle;&lt;br /&gt;    s.MarkerSize = 8;&lt;br /&gt;    s.BorderWidth = 3;&lt;br /&gt;    s.ToolTip = &quot;Wafer Id: #AXISLABEL\n&quot; + &lt;br /&gt;    &quot;Time: &lt;span style=&quot;color: red&quot;&gt;#CUSTOMPROPERTY(TIME)&lt;/span&gt;\n&quot; +&lt;br /&gt;    &quot;Y Value: #VALY&quot;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8krq19rHrf0V5qyRjtYX4eGGXRwIoFHrT3OPF8nx7yimnQ3lP7RbAp4AyWHlXPpy7s34m7RhorNuqTbVeoAWtuis35iloOmFG1OawJ0scPEuFo786xtxdsB_JYOs3aMIeMq8fKj1X2cY/s1600-h/image%25255B3%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiikIGylDHDtmoXYHJZA_4CiC2AE9Mlr7DW6GOPO3Z7YJ4AXo1XTm-XttIn25DHFhWE0waRoe0_C6Zr7Vr9QmoGe-V5VFtbxYZJzGFcdvEfVOQ8X7YAUkFUmlJd4z6SIwKvp7GjdWsILU0//?imgmax=800&quot; width=&quot;589&quot; height=&quot;260&quot;&gt;&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/4857947839437275197/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/01/c-m-chart-control-tooltip.html#comment-form' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4857947839437275197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/4857947839437275197'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/01/c-m-chart-control-tooltip.html' title='C# – M$ Chart Control 自定 ToolTip 的顯示'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiikIGylDHDtmoXYHJZA_4CiC2AE9Mlr7DW6GOPO3Z7YJ4AXo1XTm-XttIn25DHFhWE0waRoe0_C6Zr7Vr9QmoGe-V5VFtbxYZJzGFcdvEfVOQ8X7YAUkFUmlJd4z6SIwKvp7GjdWsILU0/s72-c/?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-1349784386657219997</id><published>2013-01-31T17:39:00.001+08:00</published><updated>2013-01-31T17:39:44.749+08:00</updated><title type='text'>C# – M$ Chart Control 顯示 Stacked Bar Chart.</title><content type='html'>&lt;p&gt;最近因 Requirement 的需要, 需 Drawing stacked bar chart，之前的文章已有寫過如何在 ASP.NET MVC 中使用 MS Chart Control 這個元件了, 那其 Stacked Bar Chart 需在 Series 中加入一個自訂的 Attributes (&lt;font color=&quot;#ff0000&quot;&gt;&lt;strong&gt;StackedGroupName&lt;/strong&gt;&lt;/font&gt;) 來控制，故在此記錄一下其 Code 的部份，以防後續時間一久又忘了如何使用.&lt;/p&gt;&lt;pre style=&quot;border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 98.02%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; height: 96px; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px&quot;&gt;&lt;code&gt;    Series s = new Series();&lt;br /&gt;    s.Name = &quot;SeriesName&quot;;&lt;br /&gt;    s.ChartArea = &quot;ChartArea1&quot;;&lt;br /&gt;    s.ChartType = SeriesChartType.StackedColumn;&lt;br /&gt;    &lt;span style=&quot;color: red&quot;&gt;s[&quot;StackedGroupName&quot;] = &quot;Group1&quot;;&lt;/span&gt;&lt;br /&gt;    chart.Series.Add(s);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb_zcQwVnK4nUQ_oW2-kefPD6_ZexAXU-SMQG0dCqirGaif_QHQnyO1giz5UuEK_oH7nETyjTJvD4QMzB4i5ps2tZ1HfJqc_CRBrhXQTqPTgpAiXpjUlO6KPDvUdTGDjZgB87iJ-9m0Bg/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixa563If01mFAjikPFeVhUuAG-1uhszPJa_ILJ5XZKtNFOxVkbAYkQRcszWDj7u7d2Dl_NCm2qGYyB96QnBi6yke3XfaMLUof6EC9EhfH_adEykX-ZaQExzOs1KPcyc4IXTxsfJ9qUmWE//?imgmax=800&quot; width=&quot;566&quot; height=&quot;243&quot;&gt;&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/1349784386657219997/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/01/c-m-chart-control-stacked-bar-chart.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1349784386657219997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/1349784386657219997'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/01/c-m-chart-control-stacked-bar-chart.html' title='C# – M$ Chart Control 顯示 Stacked Bar Chart.'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixa563If01mFAjikPFeVhUuAG-1uhszPJa_ILJ5XZKtNFOxVkbAYkQRcszWDj7u7d2Dl_NCm2qGYyB96QnBi6yke3XfaMLUof6EC9EhfH_adEykX-ZaQExzOs1KPcyc4IXTxsfJ9qUmWE/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-2365296804023685941</id><published>2013-01-17T16:05:00.001+08:00</published><updated>2013-01-17T16:05:55.362+08:00</updated><title type='text'>Javascript – String 增加 LeftPad 的 Function</title><content type='html'>&lt;p&gt;在 C# 中其 String 當其 Length 不足時可在前方補上所需的字元, 那在 Javascript 中並沒有此 Function 可以使用, 那使用擴充的方式來增加所需的 Function. 那如下所示：&lt;/p&gt;&lt;pre style=&quot;border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; padding-bottom: 5px; line-height: 14px; background-color: #eee; padding-left: 5px; width: 99.64%; padding-right: 5px; font-family: andale mono, lucida console, monaco, fixed, monospace; height: 112px; color: #000000; font-size: 12px; overflow: auto; border-top: #999999 1px dashed; border-right: #999999 1px dashed; padding-top: 5px&quot;&gt;&lt;code&gt;String.prototype.leftPad = function (padString, length) {&lt;br /&gt;    var str = this;&lt;br /&gt;    while (str.length &amp;lt; length)&lt;br /&gt;        str = padString + str;&lt;br /&gt;    return str;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/2365296804023685941/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2013/01/javascript-string-leftpad-function.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2365296804023685941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2365296804023685941'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2013/01/javascript-string-leftpad-function.html' title='Javascript – String 增加 LeftPad 的 Function'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-3269518490534785230</id><published>2012-11-28T15:59:00.001+08:00</published><updated>2012-11-28T15:59:12.882+08:00</updated><title type='text'>[WPF] – Debugging DataBindings</title><content type='html'>&lt;p&gt;&lt;font size=&quot;2&quot;&gt;最近從頭開始學習 WPF 其 DataBinding，那其如何 Dbugging DataBindings 的部份是我之前並沒有接觸過的，那記錄一下以後有需要時就可以拿來使用，以防跟之前一樣都是用土法鍊鋼的方式一直測試到 Binding 成功為止，也不知道那裡有問題.&lt;/font&gt; &lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIB5SNszESUIxMOowYECc1iE77kQggEDuAcKogPxy_bwVHMp_RT9sqberg0v_R1U9fm8KfI0fIbwwwM5U-3EAubJmyxNgm1qaVMtGJOxWAC_2_Wf5IqrGc2R8rp_Ra-iO2EdEfD4bdQ10//?imgmax=800&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6SSoIPKx4QzJt5e3WYwT-Ro4m_p6cDZ66i6Pda15Y78K-13S9CFe2__BQVr4wvk7m78T7LQQPjIt5aBlTSSO_Px0wb_2SxY88Q7B7okcXayZ0YiKVyaSAQz1CmZ2GJnK9nIitwh92H60//?imgmax=800&quot; width=&quot;568&quot; height=&quot;396&quot;&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG1f_S5rZGaY41SThn2T9chFHIl1pABFPSp4AhKS7h_7EU_t0q9Ual_cvW8qsFDJrdQU1QAFbjOtBMwJkkydaKUjUjOVqG6jMVgDrbtm54EqNkjyuLCargYp3jBzi06CBSWCicfZAsfn4/s1600-h/image%25255B10%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxNOFRtO5YHvYSMYf4SnhBRqx0CvpoOjOeyeSDvQjEgOi_ioLEa1yXLQ_7PJ8pLaQF_nRM6RZ2nDKN3SaXcdZZvT20NZTeCtpeKHHzwnVixjJSCCoQ_a5ywHp70jVsQsLXh5nzIPSAg-E//?imgmax=800&quot; width=&quot;569&quot; height=&quot;648&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Sbatzw1rLmmImEJjGBv5ENDBOcTiRqbizji4whelIXQwNc9a57AGQTkLDYJ-jrP05Fv97g-qR5xWFHotgtqN9yzpzGP_1pSpHRGQ2sThYybgsA2_GYBxYFCItw0UTPgdJQHYI5qHTv0/s1600-h/image%25255B15%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTonGfxvKQb6D36nAQkXNGckuV6c-__fEipgHnus4PtXuAAz3IIXgigUAj7a6aKah8qPUT8cnfEjH1jLecUSQg7CiUx50ukMJZKke_ln53b5Pfrbp7ItureXPht8ESLJKaixWoC2chQCI//?imgmax=800&quot; width=&quot;571&quot; height=&quot;508&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;font size=&quot;2&quot;&gt;按照上面所述的部份做設定即可 Debugging DataBindings 了.&lt;/font&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/3269518490534785230/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2012/11/wpf-debugging-databindings.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3269518490534785230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/3269518490534785230'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2012/11/wpf-debugging-databindings.html' title='[WPF] – Debugging DataBindings'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6SSoIPKx4QzJt5e3WYwT-Ro4m_p6cDZ66i6Pda15Y78K-13S9CFe2__BQVr4wvk7m78T7LQQPjIt5aBlTSSO_Px0wb_2SxY88Q7B7okcXayZ0YiKVyaSAQz1CmZ2GJnK9nIitwh92H60/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8207014087154934703.post-2956375632715608601</id><published>2012-11-26T14:06:00.001+08:00</published><updated>2012-11-26T14:06:32.575+08:00</updated><title type='text'>[Windows] – Registering an Application to a URL Protocol</title><content type='html'>&lt;p&gt;有些應用程式可以在 Web 按下 Hyper Link 後會開啟應用程式並傳入參數, 那此部份是如何達成的呢？在此記錄一下, 以防以後有需要時還要再重新找尋資料.&lt;/p&gt; &lt;h4&gt;&lt;a&gt;&lt;/a&gt;Registering the Application Handling the Custom Protocol&lt;/h4&gt; &lt;p&gt;To register an application to handle a particular URL protocol, add a new key, along with the appropriate subkeys and values, to HKEY_CLASSES_ROOT. The root key must match the protocol scheme that is being added. For instance, to add an &quot;alert:&quot; protocol, add an &lt;strong&gt;alert&lt;/strong&gt; key to HKEY_CLASSES_ROOT, as follows:  &lt;p&gt;&lt;strong&gt;HKEY_CLASSES_ROOT&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;alert&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;URL Protocol&lt;strong&gt; = &lt;/strong&gt;&quot;&quot; &lt;p&gt;Under this new key, the &lt;strong&gt;URL Protocol&lt;/strong&gt; string value indicates that this key declares a custom protocol handler. Without this key, the handler application will not launch. The value should be an empty string. &lt;p&gt;Keys should also be added for &lt;strong&gt;DefaultIcon&lt;/strong&gt; and &lt;strong&gt;shell&lt;/strong&gt;. The Default string value of the &lt;strong&gt;DefaultIcon&lt;/strong&gt; key must be the file name to use as an icon for this new URL protocol. The string takes the form &quot;path, iconindex&quot; with a maximum length of MAX_PATH. The name of the first key under the &lt;strong&gt;shell&lt;/strong&gt; key should be an action verb, such as &lt;strong&gt;open&lt;/strong&gt;. Under this key, a &lt;strong&gt;command&lt;/strong&gt; key or a &lt;strong&gt;DDEEXEC&lt;/strong&gt; key indicate how the handler should be invoked. The values under the &lt;strong&gt;command&lt;/strong&gt; and &lt;strong&gt;DDEEXEC&lt;/strong&gt; keys describe how to launch the application handling the new protocol.  &lt;p&gt;Finally, the &lt;strong&gt;Default&lt;/strong&gt; string value should contain the display name of the new protocol. The following example shows how to register an application, alert.exe in this case, to handle the &lt;strong&gt;alert&lt;/strong&gt; protocol.  &lt;p&gt;&lt;strong&gt;HKEY_CLASSES_ROOT&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;alert&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;(Default) = &quot;URL:Alert Protocol&quot;&lt;br&gt;URL Protocol&lt;strong&gt; = &lt;/strong&gt;&quot;&quot;&lt;br&gt;&lt;strong&gt;DefaultIcon&lt;/strong&gt;&lt;br&gt;(Default) = &quot;alert.exe,1&quot;&lt;br&gt;&lt;strong&gt;shell&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;open&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;command&lt;/strong&gt;&lt;br&gt;(Default) = &quot;C:\Program Files\Alert\alert.exe&quot; &quot;%1&quot; &lt;p&gt;When a user clicks a link registered to your custom URL protocol, Internet Explorer launches the registered URL protocol handler. If the specified &lt;strong&gt;open&lt;/strong&gt; command specified in the registry contains a &lt;strong&gt;%1&lt;/strong&gt; parameter, Internet Explorer passes the URI to the registered protocol handler application.  &lt;p&gt;詳細內容請參考 : &lt;a title=&quot;http://msdn.microsoft.com/zh-tw/library/aa767914(v=vs.85).aspx&quot; href=&quot;http://msdn.microsoft.com/zh-tw/library/aa767914(v=vs.85).aspx&quot;&gt;http://msdn.microsoft.com/zh-tw/library/aa767914(v=vs.85).aspx&lt;/a&gt; …&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://jain0921.blogspot.com/feeds/2956375632715608601/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://jain0921.blogspot.com/2012/11/windows-registering-application-to-url.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2956375632715608601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8207014087154934703/posts/default/2956375632715608601'/><link rel='alternate' type='text/html' href='http://jain0921.blogspot.com/2012/11/windows-registering-application-to-url.html' title='[Windows] – Registering an Application to a URL Protocol'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/14213901707982868642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>