前言
WPF 實在是很棒的一個 Framework,而且在開發設計時,Visual Studio IDE 的輔助,讓我們的開發更具生產力。但也因為如此,當我們不朝預設的開發方式時,就容易遇到一些「地雷」。今天我就踩到一個。
問題
問題的由來是有演變過程的。以下就一步步的演進吧。
步驟1: 標準的 Style
我按標準步驟產生了一個 WPF Application後,在 MainWindow.xaml 上放了一個 Button。
Xaml 如下, 非常簡單
<Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="40,36,0,0" Name="button1" VerticalAlignment="Top" Width="75" /> </Grid> </Window>
步驟2: 套用標準的 Style 到每一個 Button
為了讓整個程式的按鍵看來有一致的外觀,我在 App.xaml 上增加了 Button Style。App.xaml 如下,也非常的 easy
<Application x:Class="WpfApplication2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <Style TargetType="Button"> <Setter Property="Background" Value="LightBlue" /> </Style> </ResourceDictionary> </Application.Resources> </Application>
而無論在開發階段或執行階段,Button 的樣式果然成我預期的背景顏色LightBlue 淺藍色。
步驟3:移除 StartupUri
因故,我必須移除 App.xaml 中的 StartupUri,並自行建立 MainWindow 的 instance。修改後的 App.xaml如下
<Application x:Class="WpfApplication2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <!--注意到我移除了 StartupUri--> <Application.Resources> <ResourceDictionary> <Style TargetType="Button"> <Setter Property="Background" Value="LightBlue" /> </Style> </ResourceDictionary> </Application.Resources> </Application>
而 App.xaml.cs 如下
using System.Windows; namespace WpfApplication2 { public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var mainWindow = new MainWindow(); mainWindow.Show(); } } }
程式可以執行,但問題來了:執行時期,Button 的樣式跑掉了。
這是怎麼一回事?開發的Designer 仍然是淺藍色背景--我要的樣式啊!
原因
原因是:開發工具太強了,幫我們做了太多的事。將原來的 StartupUri 加回去,並在 Solution Explorer 下找到 obj\Debug\ 可以找到一堆由 Visual Studio 幫我們產生的程式碼。
打開 App.g.i.cs ,可以找到 InitializeComponent 這個方法。可以看到它是如何幫我們自動載入 Resource 的.
一旦我們將 StartupUri 移除掉,這段程式就會變化。整個 InitializeComponent 方法就不見了!!
這就是原因所在。
解決
既然找到了原因,當然就知道要怎麼解了。方法有二。
第一個方法是自己補上消失的程式,並且自己將消失的 style 補上。這個方法難度較高,而且不好維護。我採用第二個方法:自訂一個 ResourceDictionary。
新增一個 ResourceDictionary 並命名為 AppResource.xaml, 並將原來在 App.xaml 的 style 移到這裡。
AppResource.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="Button"> <Setter Property="Background" Value="LightBlue" /> </Style> </ResourceDictionary>
改用 。修改App.xaml 如下
<Application x:Class="WpfApplication2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <!--注意到我移除了 StartupUri--> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="AppResource.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
然後,執行時期的 Button 樣式就回來了。
結論
WPF 實在設計的很棒,而 IDE 的開發輔助也讓我們快速的完成常見的需求。只是在 IDE 快速開發的背後,我們常常忽略了原來應該是我們要做的事。一旦不符合原 IDE 的快速開發條件時,就摸不著頭緒了。
沒有留言:
張貼留言