[心得] IronRuby & C# & WPF & XAML
不知道這篇可不可以發在這,不過這是一個想用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
03/17 14:33, 1F
→
03/17 15:57, , 2F
03/17 15:57, 2F
→
03/17 15:57, , 3F
03/17 15:57, 3F
→
03/26 16:45, , 4F
03/26 16:45, 4F
推
10/09 17:31, , 5F
10/09 17:31, 5F
Ruby 近期熱門文章
PTT數位生活區 即時熱門文章