作者mars90226 (火星人)
看板Ruby
标题[心得] IronRuby & C# & WPF & XAML
时间Sat Mar 17 13:07:20 2012
不知道这篇可不可以发在这,不过这是一个想用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="
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
1F:推 hst1805:有趣的研究不过好奇怎样的需求要用ironRuby+WPF? 03/17 14:33
2F:→ mars90226:大概就是把好用的gem搬过来吧XD 03/17 15:57
3F:→ mars90226:Rails也可以啊~ 03/17 15:57
4F:→ ryudo:GJ! 03/26 16:45
5F:推 ireullin:推^^ 10/09 17:31