[心得] IronRuby & C# & WPF & XAML

看板Ruby作者 (火星人)時間12年前 (2012/03/17 13:07), 編輯推噓2(203)
留言5則, 4人參與, 最新討論串1/1
不知道這篇可不可以發在這,不過這是一個想用IronRuby開發WPF的人的嘗試心得 -----正文----- 搞了N天終於成功了,趕快來筆記一下 目的: 想靠IronRuby建立WPF應用程式(利用XAML),而且還想要編譯成exe檔以便散播 想法: 藉由C#去呼叫IronRuby,再利用C#編譯 首先,開啟Visual Studio建立C#專案(我用Console專案,不過沒差) 然後把該加進來的"參考"(就是.NET的library)加進來: IronRuby, IronRuby.Libraries, IronRuby.Libraries.Yaml //IronRuby Microsoft.Scripting, System, System.Xaml, Windows.Base PresentationCore, PresentationFramework //WPF (我還多引入一個 Microsoft.CSharp,不過我想應該沒差) 然後建立一個ruby file "wpf.rb": require "PresentationFramework" require "PresentationCore" xaml = File.read("test.xaml").gsub(/\A[^<]*/,"") # 砍掉討厭的BOM (3 bytes) @root = System::Windows::Markup::XamlReader.parse xaml @root.find_name("button").click do |s, e| @root.find_name("msg").text = "Changed!" end app = System::Windows::Application.new app.run @root 在建立一個xaml file "test.xaml": <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="" rel="nofollow">http://schemas.microsoft.com/winfx/2006/xaml"> <StackPanel> <TextBlock x:Name="msg" Text="Hello, WPF!" /> <Button x:Name="button">Click!</Button> </StackPanel> </Window> 最後建立一個C# file "IronRubyFromCSharp.cs": using Microsoft.Scripting.Hosting; using IronRuby; using System.Threading; namespace IronRubyFromCSharp { class IronRubyFromCSharp { public static void Main(string[] args) { Thread thread = new Thread(() => { var engine = Ruby.CreateEngine(); engine.ExecuteFile("wpf.rb"); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); } } } 好了,接下來我們必須要讓Visual Studio知道哪些檔案是需要包進安裝程式 在右方的方案總管(Solution Explorer)面板選取ruby, xaml檔案,右鍵看屬性 然後在屬性面板裡的"建置動作"中選取"內容" 然後再打開"專案"(Project)的屬性(不是"方案"(Solution)!!) 點選最下面的發行,有個"應用程式檔案"的按鈕 把裡面的東西都改成包含(避免客戶端沒有IronRuby) 而且可以把剛剛的建立的檔案加進安裝程式 最後就發行看看咯~ -----解說----- 好唄,我們來看一下為什麼一個簡單的WPF程式會變得這麼複雜 最終的其實只有一個文字+一個按鈕,按鈕按下去會改變文字的內容 不過我要省略C#&WPF&XAML基礎知識,這篇的重點是IronRuby,因此我只大略說 WPF建議使用XAML來畫應用程式的介面,XAML的內容應該很好懂 首先是ruby file: 把WPF必要檔案require進來:"PresentationFramework","PresentationCore" xaml = File.read("test.xaml").gsub(/\A[^<]*/,"")就是讀取XAML,順便砍掉BOM @root = System::Windows::Markup::XamlReader.parse xaml就是把xaml拿去parse 此時的@root就是一個System.Windows.Window物件 //請見XAML內容 再把@root扔給System.Windows.Application去run就行了 所以後面就看到 app = System::Windows::Application.new app.run = @root 如果是直接用ir去interpret IronRuby檔案的話,這樣就行了 不過我們需要C#的編譯,所以在看到C#檔案: 前面就是using .NET library: Script Host & IronRuby 我們多using一個System.Threading,這是有原因的 WPF需要在"單一執行緒Apartment"(STA)中執行(別問我為什麼= =,我猜是怕干擾) 所以直接去呼叫IronRuby是不行的! 因此我們建立一個Thread,把呼叫IronRuby的工作交給它 設定Thread為STA,再讓它執行 終於大功告成了!!! -----來列一下我遇到的瓶頸----- ˙Debug時可以讀到ruby file,發行時跳出LoadError ˙用Visual Studio建立的檔案有BOM,但是parse出錯時只顯示XamlParseException ˙砍掉BOM後去run,跳出"執行緒須為STA,因為很多UI元件都需要STA" -----後記----- 根據網路上的回答,STA這個設定似乎從.NET以前就有了,大部分程式要求STA 不過,我跟Windows Application不熟XD -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 125.228.42.170

03/17 14:33, , 1F
有趣的研究不過好奇怎樣的需求要用ironRuby+WPF?
03/17 14:33, 1F

03/17 15:57, , 2F
大概就是把好用的gem搬過來吧XD
03/17 15:57, 2F

03/17 15:57, , 3F
Rails也可以啊~
03/17 15:57, 3F

03/26 16:45, , 4F
GJ!
03/26 16:45, 4F

10/09 17:31, , 5F
推^^
10/09 17:31, 5F
文章代碼(AID): #1FP1mBUH (Ruby)
文章代碼(AID): #1FP1mBUH (Ruby)