接下來就是屬於藝術設計或是稱做 ART / UI Designer 的主要工作了, 把畫面給架構出來,
在 WPF 裡面架構畫面主要是採用 XAML,跟 XML 的描述方式差不多, 當然, 對 ART Designer
來說可以用更直覺化的工具來產生畫面, 例如 Blend Express, 由於物件已經完成,
所以可以即時反應所給予的參數, 並呈現於設計工具裡面, 也就是立即達到所見及所得的效果,
而非憑空想像, 這點對 ART Designer 幫助很大, 不會再有跟 Programmer 溝通不良的問題,
當然利用 XML 架構也有許多好處, 比如說可攜性, 交換性, 活用性, 架構性 都相當的完善與便利,
舉例來說, 各位只要把這個 XAML 複製過去, 即可把整各 UI 架構給複製過去, 如果要改變球體,
也只要修改其中的參數, 在設計工具的畫面裡面, 立可就能呈現出來修改參數後的效果,
這裡可以見到, 微軟的野心, 就如同作業系統一樣, 將底層平台架構完整, 將來勢必又是被”教育”
成”傻瓜使用者”, 只要如同操作傻瓜相機一般, 一個按鈕搞定一切, 呵呵~~
<window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1.Shapes"
Title="Window1" Height="610.122" Width="633.46" Name="Window1">
<grid>
</grid><grid .RowDefinitions>
<rowdefinition Height="105.021*" />
<rowdefinition Height="499.479*" />
</grid>
<grid Grid.Row="0">
</grid><grid .RowDefinitions>
<rowdefinition Height="*" />
<rowdefinition Height="*" />
<rowdefinition Height="*" />
</grid>
<grid .ColumnDefinitions>
<columndefinition Width="198.373*" />
<columndefinition Width="546.447*" />
</grid>
<!--<SnippetSliders>-->
<slider Grid.Row="0" Grid.Column ="1" Name="slider1" Width="448.605680056927"
HorizontalAlignment="Left" Margin="0,0,0,7.105427357601E-15"
Value="{Binding ElementName=sphere, Path=ThetaDiv}" Minimum="1" Maximum="100"/>
<slider Grid.Row="1" Grid.Column ="1" Name="slider2"
Margin="5.6843418860808E-14,2.1316282072803E-14,0,0"
Value="{Binding ElementName=sphere, Path=PhiDiv}" Minimum="1" Maximum="100"/>
<slider Grid.Row="2" Grid.Column ="1" Name="slider3"
Value="{Binding ElementName=sphere, Path=Radius}" Margin="5.6843418860808E-14,-2.8421709430404E-14,0,0"
Minimum="0" Maximum="2" />
<!--</SnippetSliders>-->
<label Margin="0,0,0,0" Grid.Row="0" Name="label1">Theta</label>
<label Margin="0,0,0,0" Grid.Row="1" Name="label2">Phi</label>
<label Margin="0,0,0,0" Grid.Row="2" Name="label3">Radius</label>
<label Margin="62,0,0,0" Name="Label4" Content="{Binding ElementName=slider1, Path=Value}"/>
<label Content="{Binding Path=Value, ElementName=slider2}" Margin="62,0,0,0" Name="Label5" Grid.Row="1" />
<label Content="{Binding Path=Value, ElementName=slider3}" Margin="62,0,0,0" Name="Label6" Grid.Row="2" />
<!--<SnippetViewport3D>-->
<viewport3d x:Name="vport" Grid.Row="1">
<!-- The camera for the scene -->
</viewport3d><viewport3d .Camera>
<perspectivecamera Position="0,0,4" />
</viewport3d>
<local :Sphere x:Name="sphere" Text="1234567890 10 11 12 13 14 15">
</local><local :Sphere.Transform >
<transform3dgroup>
<translatetransform3d OffsetX="0" OffsetY="0" OffsetZ="0"/>
<scaletransform3d ScaleX="1" ScaleY="1" ScaleZ="1"/>
<rotatetransform3d CenterX=" 0" CenterY=" 0" CenterZ=" 0">
</rotatetransform3d><rotatetransform3d .Rotation >
<axisanglerotation3d x:Name="rotate" />
</rotatetransform3d>
</transform3dgroup>
</local>
<!-- Lights -->
<modeluielement3d>
</modeluielement3d><modeluielement3d .Model>
<model3dgroup>
</model3dgroup><model3dgroup .Children>
<directionallight Color="WhiteSmoke" Direction="0,0,-1" />
</model3dgroup>
</modeluielement3d>
<label Grid.Row="1" Height="29" HorizontalAlignment="Left" Name="Labelx1" VerticalAlignment="Top" Width="58">Label</label>
<label Height="29" HorizontalAlignment="Left" Margin="62,0,0,0" Name="Labely1" VerticalAlignment="Top" Width="58" Grid.Row="1">Label</label>
<button Grid.Row="1" Height="21" HorizontalAlignment="Right" Margin="0,8,14,0" Name="Button1" VerticalAlignment="Top" Width="51">Button</button>
<label Grid.Row="1" Height="21" HorizontalAlignment="Left" Margin="0,27.604,0,0" Name="Labelx2" VerticalAlignment="Top" Width="47">Label</label>
<label Height="21" HorizontalAlignment="Left" Margin="62,27.604,0,0" Name="Labely2" VerticalAlignment="Top" Width="47" Grid.Row="1">Label</label>
<label Height="21" HorizontalAlignment="Left" Margin="115.854,27.604,0,0" Name="Labelz2" VerticalAlignment="Top" Width="47" Grid.Row="1">Label</label>
<label Height="29" HorizontalAlignment="Left" Margin="115.854,0,0,0" Name="Labelz1" VerticalAlignment="Top" Width="58" Grid.Row="1">Label</label>
<label Height="21" HorizontalAlignment="Left" Margin="0,54,0,0" Name="Labelx3" VerticalAlignment="Top" Width="47" Grid.Row="1">Label</label>
<label Height="21" HorizontalAlignment="Left" Margin="62,54,0,0" Name="Labely3" VerticalAlignment="Top" Width="47" Grid.Row="1">Label</label>
<label Height="21" HorizontalAlignment="Left" Margin="115.854,54,0,0" Name="Labelz3" VerticalAlignment="Top" Width="47" Grid.Row="1">Label</label>
<!--</SnippetViewport3D>-->
</window>
上面程式中大部分都在描述整體畫面, 所以不詳加介紹, 請各位讀者大大自行參閱 WPF 文件,
其中只有兩個地方要特別說明的是, 1 Data Binding 的觀念, 因為之前的物件參數交由 vhost 管理
所以這裡可以輕易的達成 Databinding, 這可以節省許多需要動用程式設計師來撰寫程式的麻煩,
只要由 ART Designer 直接把兩物件的直關聯起來便可以達成互動效果, 例如以下我們把 sliderbar
跟我們自行製作的物件中的 ThetaDiv 關聯起來, 就可以直接用 sliderbar 來調整這個參數值,
Value=”{Binding ElementName=sphere, Path=ThetaDiv}”, 這樣一行就取代掉 Programming
第 2 點, 物件相容的整合性, 由於我們在設計元件時, 繼承了 UIElement 的特性, 所以很多各種
應用可以直接套用, 例如各種不同的 Transform, 原本在這裡僅需要一行指令(如下) 即可
<local:Sphere x:Name=”sphere” Text=”1234567890 10 11 12 13 14 15″ />
但是 ART Designer 可以輕易透過 Transform 來改變他原有的角度, 大小, 位置,
所以在這個 XAML 裡面加入 Transform 宣告, 來測試他即時再 UI 上面呈現的結果,
這裡比較需要說明的是, 因為我們程式需要直接掌握 Transform 參數, 才能正確轉換鼠標位置,
所以在 Transofrm 裡面去定義任何參數, 如 <AxisAngleRotation3D x:Name=”rotate” />
其實是沒有意義的, 因為這個定義很快會在我們的程式裡面把它給覆蓋掉, 下一篇, 我們將介紹
如何讓這個球體能夠互動起來, 其中最難理解的地方應該是在 3D 空間座標的轉換, 因為透過 Transform
之後, 要在一個 3D 立體物件上偵測滑鼠的點擊(Hittest), 雖然 WPF 有相當好用的物件可以使用,
但基本上這物件取得的座標是原本 3D 物件建構時的座標系, 而非經過 Transform 轉換後的座標,
所以在轉換上面的下一番工夫, (呵呵~也是簡單幾個指令啦), 如此才能夠正確追蹤到滑鼠由標的正確位置
近期迴響