2008年11月26日 星期三

應用程式如何得知 "控制台" --> "地區語言選項" 的改變

系統事件的使用者喜好設定變更時可以藉由 命名空間Microsoft.Win32 的 SystemEvents.UserPreferenceChanged 事件進行通知,

以下程式是註冊該事件

Visual Basic
AddHandler SystemEvents.UserPreferenceChanged, AddressOf SystemEvents_UserPreferenceChanged DisplayCultureInfo()
C#
SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(SystemEvents_UserPreferenceChanged);

它的事件參數 UserPreferenceChangedEventArgs 的 Category 屬性會傳入變更的事件類別, 如果是 "地區語言選項" 的改變, 是 UserPreferenceCategory.Locale

事件程序如下:

Visual Basic
Sub SystemEvents_UserPreferenceChanged(ByVal sender As Object, ByVal e As Microsoft.Win32.UserPreferenceChangedEventArgs)
        If e.Category = UserPreferenceCategory.Locale Then
            DisplayCultureInfo()
        End If
    End Sub
C#
static void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
if (e.Category== UserPreferenceCategory.Locale )
DisplayCultureInfo();
}

Thread.CurrentThread.CurrentCulture 會回傳目前執行緒的文化特性, 只有應用程式載入初期會寫入這個值, 所以控制台改變, 這個值並不會跟著異動, 若要取得控制台最新的文化特性, 必須先將目前的快取資料清除, 呼叫ClearCachedData 方法. 當快取被清除時, 將會自動取得控制台最新的設定.

Visual Basic
    Sub DisplayCultureInfo()
        Thread.CurrentThread.CurrentCulture.ClearCachedData()
        Dim UsersCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
        Dim region As New RegionInfo(UsersCulture.Name)
        Console.WriteLine(region.DisplayName)
        Console.WriteLine(region.EnglishName)
        Console.WriteLine(region.NativeName)
        Console.WriteLine(region.CurrencyEnglishName)
        Console.WriteLine(region.CurrencyNativeName)
    End Sub
C#
private static void DisplayCultureInfo()  
{
Thread.CurrentThread.CurrentCulture.ClearCachedData();
CultureInfo UsersCulture = Thread.CurrentThread.CurrentCulture;
RegionInfo region = new RegionInfo(UsersCulture.Name);
Console.WriteLine(region.DisplayName);
Console.WriteLine(region.EnglishName);
Console.WriteLine(region.NativeName);
Console.WriteLine(region.CurrencyEnglishName);
Console.WriteLine(region.CurrencyNativeName);
}

2008年11月9日 星期日

ASP.NET 專案的 Profile

如果你使用Visual Studio的 File --> New Web Site 來設計專案時, Web.config定義好Profile 的屬性並存檔之後, 在程式中使用Profile 會有Intellisence 自動列表相關屬性.

WebSite模式是將profile的properties 建立成一個Strongly Type, 請看下圖:

建立成一個Strongly Type

可是如果使用File --> New Project , 建立ASP.NET Web Application時, Web.config定義好Profile 的屬性並存檔之後, 在程式中使用Profile, Intellisence 所列表的資訊竟與前者完全不同, 而且並沒有定義好的屬性... 真是傷腦筋!!

用Object Browser 完全看不到Strongly type 的Profile類別...

2

這難道就不能用Profile 的功能了嗎? 答案: 並不是...

只是寫起來真的很麻煩, 必須使用HttpContext.Current.Profile的SetPropertyValue及GetPropertyValue存取屬性內容.

例如, 修改FirstName 的屬性

HttpContext.Current.Profile.SetPropertyValue ("FirstName", "Lisa")

讀取FirstName的屬性

Dim FName As String = HttpContext.Current.Profile.SetPropertyValue ("FirstName").ToString()

 

Ps.這是上課時同學發現Profile 沒有IntelliSense, 仔細看一下Soluction Explorer 才發現是專案模式而不是Web Site模式....但還是感到相當意外, 竟然在專案模式下的Profile不是Strongly type..., 只好用原始方式找答案.

Ps.用VS2005與VS2008 的Project 模式的Profile 都不是Strongly type.

ASP.NET快取之SQL相依性

除了原來的CacheDependency 針對File相依性決定移除Cache之外, ASP.NET 2.0 新增了SQL 相依性的功能, 是針對SQL Server 的Table 或是查詢進行變更時, 移除Cache 的策略. 它提供了兩種方式,

  1. 輪詢模式
  2. 查詢通知

輪詢模式

只支援SQL Server 7.0 (含)以上的版本, 由ASP.NET主動定期向SQL Server詢問Table 是否遭到異動, 以決定是否移除快取.

使用輪詢模式必須執行以下動作:

  1. 執行aspnet_regsql, 在資料庫及資料表設定異動檢查

    Aspnet_regsql –S 伺服器名稱 –E –d 資料庫 -ed –t 資料表 –et

  2. asp.net 的web.config 設定輪詢的時間及連線字串
    <caching>
    <sqlCacheDependency enabled="true" pollTime="1000">
    <databases>
    <add name="NWDB" connectionStringName="NorthwindConnectionString" pollTime="1000"/>
    </databases>
    </sqlCacheDependency>
    </caching>


  3. asp.net 的網頁要用到SQL Cache Dependency 時指定web.config 的SqlCacheDependencies 的項目名稱

    <%@ OutputCache Duration="秒數" VaryByParam="參數清單" SqlDependency = "資料庫快取相依性名稱:資料表" %>


    <%@ OutputCache Duration="3600" VaryByParam="None" SqlDependency = "NWDB:Categories;NWDB:Products" %>




查詢通知


只支援SQL Server 2005以上的版本, 由ASP.NET向SQL Server 註冊事件, SQL Server 只要發現查詢有異動, 便主動通知有註冊的服務.


使用查詢通知必須執行以下動作:



  1. 在SQL Server 啟用通知功能

    ALTER DATABASE Pubs SET ENABLE_BROKER ;


  2. 在ASP.NET的Global.asax, Application_Start 時向SQL Server註冊事件

    Application_Start事件啟動接聽程式


    SqlDependency.Start("連線字串")


    在Application_End事件停用接聽程式


    SqlDependency.Stop("連線字串")


  3. 網頁要用到時, 在相關的SqlCacheDependency 設定 CommandNotification

    <%@ OutputCache Duration="秒數" VaryByParam="參數清單" SqlDependency = "CommandNotification" %>


2008年11月8日 星期六

內嵌DropDownList, 欄位值為Null時怎麼辦

ASP.NET 2.0 小技巧

在GridView在編輯模式時內嵌DropDownList, 當對應的那筆資料欄位值為Null時怎麼辦?

這是在上ASP.NET 課程時同學問的問題.

 

欄位Null值時那個DropDownList 的SelectedValue無法對應到對的值, 所以網頁就會出現錯誤. 怎麼解決呢?

如果那個欄位不能設計成不可為Null值, 那只好在DropDownList裡多加一個可以給SelectedValue對應到的值.

作法是:

當Null值被對Building 到SelectedValue時, 那個值實際上是一個空字串.

所以可以在DropDownList的Items 加上一個項目, Text 為"請選擇", Value為空值.

<asp:ListItem Value="">請選擇</asp:ListItem>

而且必須設定DropDownList的AppendDataBoundItems屬性為"True", 整個TemplateField看起來像這樣:

<asp:TemplateField HeaderText="CategoryID" SortExpression="CategoryID">   
    <EditItemTemplate>
        <asp:DropDownList ID="DropDownList1"  runat="server"
            DataSourceID="SqlDataSource2" DataTextField="CategoryName"
             DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
           AppendDataBoundItems="True">
            <asp:ListItem Value="">請選擇</asp:ListItem>
        </asp:DropDownList>
        <asp:SqlDataSource ID="SqlDataSource2" runat="server"
            ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories]">
        </asp:SqlDataSource>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label1" runat="server" Text='<%# Bind("CategoryID") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

就可以了.

1

2008年11月4日 星期二

WPF 的Command 是什麼?

WPF 隨手筆記

先別管Command 是什麼?

首先我們先回到傳統Windows Forms 的觀念裡, 如果你需要一個功能存檔功能, 你會怎麼設計?

一定很多人馬上舉手說, 我知道: "寫在Button 的 Click 事件", 或是有人會說 "建立一組選單, 在選單項目的事件寫上存檔的功能" ...等.

OK, 那如果同時要提供快捷鍵, 工具箱也有對應功能呢? 當然這在Windows Forms裡不難辦到.

 

相同的問題在WPF 裡要怎麼設計, 可以用相同的方式來做.

不過WPF提供了更聰明重用性更高的 Command, Command 的觀念是將這些可能用Button, Menu, ToolBar, 快捷鍵呼叫的功能統一定義在Command 裡, 以上面這個例子, 我可以設計一個叫Save 的Command, 然後呢, 如果需要用在某個Button, 或是任何控制項上以及快捷鍵, 那麼就將Command 與控制項或快捷鍵做 Binding , 這樣畫面設計上就會具有很大的彈性.

WPF為省去開發者寫一堆程式也內建了不少的Command, 例如常用的Copy, Paste, Cut...等功能. 如果沒有內建Command 再自行實作ICommand介面.

什麼是Dependency Property

WPF 隨手筆記

中文譯為依存屬性, 是WPF 引進的新屬性.

為何需要Dependency Property?

先看看一般.NET 物件, 一般Windows 控制項的屬性皆為Instance Property, 以Button為例, 若Button有96個Property, 那麼建立一個Button物件, 就得佔用96Property 所需的空間, 當然Window Forms 2.0的Control屬性或許沒有那麼多, 也就不會考慮佔用太多記憶體空間的問題.

但是WPF 的控制項可以提供相當高彈性的畫面設計, 相對的所需的屬性就會很多, 可又未必每個屬性都會用的到, 若全部設計成Instance 的Property, 那WPF 應用程式的記憶體最低需求將會很可觀.

於是WPF 引進Dependency Property 的觀念, 將一些Property 從控制項的Instance Property(也就是傳統作法)抽離 改為Dependency Property.

那到底什麼是Dependency Property?

Dependency Property 是一個存在System.Windows.DependencyObject所延伸的類別的靜態屬性, 那些不絕對需要用的屬性在需要用時就將它放置在這個DependencyObject之中, 以提升記憶體的可用性.

在使用WPF Controls 你可以不用太在意屬性是Dependency Property或Instance Property, 因為它的用法就像一般Property 的使用方式一樣, 那些記憶體配置的細節都被包裝在類別之中了.

Dependency Property 帶來的好處

除了節省記憶體空間之外, 因為處理成Dependency Property, 在屬性值變更時它提供了變更告知的功能.

Dependency Property 沒有改變設定屬性的程式寫法, 確意外的改變了傳統事件的寫法, 例如, 傳統上若要判知滑鼠進入控制項範圍之內, 會在MouseEnter事件上進行處理.

// 當滑鼠移到按鈕上時將前景顏色改為藍色
void Button_MouseEnter(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null) b.Foreground = Brushes.Blue;
}
// 當滑鼠移出按鈕時將前景顏色改回黑色
void Button_MouseLeave(object sender, MouseEventArgs e)
{
Button b = sender as Button;
if (b != null) b.Foreground = Brushes.Black;
}





有了Dependency Property 若要得知滑鼠進入控制項範圍除了原本的MouseEnter事件之外, 另可從IsMouseOver(依存)屬性得知, 也就是說, 連帶的若要在移入時變更背景色, 除了寫傳統事件程式外, 還有另一個更簡單的選擇, 那就是使用XAML的Trigger 觀念.






<Button Margin="186.6,148,277.4,216" x:Name="button">  
<Button.Style>
<Style TargetType="{x:Type Button}" >
<Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Foreground" Value="Blue" />
    </Trigger>
</Style.Triggers>
</Style>
</Button.Style>
OK
</Button>



你不用擔心這段Trigger 元素沒有描述滑鼠移出時改回原來的色彩, 因為它會很聰明的自動改回去.







參考"Windows Presentation Foundation 新一代使用體驗開發實務"

(此書譯自原文:Windows Presentation Foundation UIeashed) 一書的第三章

2008年11月3日 星期一

一個控制項繫結多個欄位

WPF隨手筆記

WPF 的資料繫結允許多個欄位與一個控制項繫結, 使用以下步驟說明:

  1. 撰寫一類別, 實作IMultiValueConverter介面, 處理多個欄位連接成一個值的作業
        public class NameConverter : IMultiValueConverter {

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    string name;
    name = values[0] + " " + values[1];
    return name;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
    string[] splitValues = ((string)value).Split(' ');
    return splitValues;
    }

    }



  2. 在Windows.Resource宣告這個類別為資源
        <Window.Resources>    
            <c:NameConverter x:Key="NameConverter"/>
            <ObjectDataProvider x:Key="NorthwindDataSetDS" ObjectType="{x:Type WpfDataBinding:NorthwindDataSet}" d:IsDataSource="True"/>
        </Window.Resources>

        <Window.DataContext>
            <Binding Path="Employees" Mode="Default" Source="{StaticResource NorthwindDataSetDS}"/>
        </Window.DataContext>



  3. 在控制項要繫結的屬性上使用MultiBinding設定Converter及繫結的欄位
    <TextBox Margin="32,80,69.6,0" VerticalAlignment="Top" Height="48" TextWrapping="Wrap">    
                <TextBox.Text>
                    <MultiBinding Converter="{StaticResource NameConverter}"
                        ConverterParameter="FormatLastFirst">
                        <Binding Path="FirstName" />
                        <Binding Path="LastName" />
                    </MultiBinding>
                </TextBox.Text>
            </TextBox>




繫結Northwind的Employees Table, 執行結果:



1

2008年10月31日 星期五

繫結多個不同的集合

WPF 隨手筆記

在WPF 裡若有多個來源 (不同的集合或Table...) 想列在一個清單裡, 除了寫程式之外, 有更簡單的方法嗎?

答案是使用CompositeCollection 類別.

  1. 先定義資料來源

    Window.Resources定義資料來源SuperStarts是一個集合類別, HistoryHeroesData 是一個XML內容

    <Window.Resources>       
    <c:SuperStars x:Key="SuperStartsData"/>
    <XmlDataProvider x:Key="HistoryHeroesData" XPath="HistoryHeroes/Hero">
    <x:XData>
    <HistoryHeroes xmlns="">
    <Hero Name="關公" />
    <Hero Name="花木蘭" />
    <Hero Name="成吉思汗" />
    <Hero Name="岳飛" />
    <Hero Name="文天祥" />
    <Hero Name="鄭成功" />
    </HistoryHeroes>
    </x:XData>
    </XmlDataProvider>

    <DataTemplate DataType="{x:Type c:SuperStar}">
    <TextBlock Text="{Binding Path=Name}" Foreground="Blue"/>
    </DataTemplate>

    <DataTemplate DataType="Hero">
    <TextBlock Text="{Binding XPath=@Name}" Foreground="Green"/>
    </DataTemplate>
    </Window.Resources>


  2. 資料繫結, 使用CompositeCollection

    CompositeCollection裡使用CollectionContainer定義資料來源


    <ListBox Name="myListBox" Height="300" Width="200" Background="White">       
    <ListBox.ItemsSource>
    <CompositeCollection>
    <CollectionContainer Collection="{Binding Source={StaticResource SuperStartsData}}" />
    <CollectionContainer Collection="{Binding Source={StaticResource HistoryHeroesData}}" />
    <ListBoxItem Foreground="Red">Other Listbox Item 1</ListBoxItem>
    <ListBoxItem Foreground="Red">Other Listbox Item 2</ListBoxItem>
    </CompositeCollection>
    </ListBox.ItemsSource></ListBox>



執行結果:


執行結果



SuperStar是一個類別檔, 以下是它的原始程式:


using System.Collections.ObjectModel;
class SuperStar
{
public string Name{ get; set;}
}
class SuperStars : ObservableCollection<SuperStar>
{
public SuperStars():base() {
Add(new SuperStar() { Name = "劉德華" });
Add(new SuperStar() { Name = "張曼玉" });
Add(new SuperStar() { Name = "劉嘉玲" });
Add(new SuperStar() { Name = "梁朝偉" });
}
}


參考來源: http://msdn.microsoft.com/en-us/library/system.windows.data.compositecollection.aspx

2008年10月26日 星期日

如何在VS 2008對預存程序偵錯

如果要在VS2008 直接對預存程序偵錯的話,

直接使用伺服器總管用有權限的帳號連到資料庫, 然後開啟該預存程序設定中斷點按右鍵選Step Into即可開始偵錯.

這個很簡單.

可是如果要對ADO.NET 的程式碼一路進行偵錯到預存程序, 那麼就必須要有幾個條件了!!

  1. 伺服器總管連到資料庫, 開啟預存程序, 在預存程序設定中斷點.
  2. 在程式碼執行預存程序的位置設定中斷點
  3. 在專案屬性設定, 啟用SQL Server偵錯

    1

  4. 伺服器總管那個連線上, 設定應用程式偵錯

    2

2008年10月18日 星期六

如何控制內容物件的位置及大小

WPF 隨手筆記

Canvas

是一個很像傳統Windows Form設計的容器, 控制項放進去時使用Top, Left決定物件的位置, Width, Height決定物件的大小.

 

Grid

很像HTML的Table, 可以將控制項放在格子內, 如果將Grid以單格使用, 效果很像Canvas.

不過, Grid是內的控制項可以使用Width, Height, Margin, HorizontalAlignment, VerticalAlignment屬性來決定控制項的位置及大小.

  1. 當Width及Height沒有設定或為Auto時(同時HorizontalAlignment, VerticalAlignment屬性不是Stretch時)控制項的大小會依據控制項的內容決定, Ex.Button的Content屬性的大小.
  2. HorizontalAlignment, VerticalAlignment屬性, 如果控制項的Width, Height沒有設定或者為Auto, 這兩個對齊屬性設定成Stretch也會影響控制項的大小, 同時Margin的Right及Bottom對於大小也會有作用, 例如Button設成Stretch以及Margin的Right及Bottom都設為10, 那麼Button會擴展到與右下邊界距離10的大小.

第一種情況: Save按鈕的大小依據內容大小決定.

第1種情況

第二種情況: 111按鈕, 根據水平垂直對齊方向為Stretch擴展大小, 同時與格子的右邊界維持10, 下邊界維持30.

第二種情況

在使用Expression Blend時用到Grid做為LayoutRoot, 在視窗的左上方會有一個按鈕, 可以切換Layout mode, 有兩種模式:

  • Grid is in Canvas layout mode
  • Grid is in Grid layout mode

in Canvas layout mode

上面兩張圖都是在這種模式下, 選取物件時, 只會出現物件的邊界選取圓點, 可以利用這些選取圓點拖拉物件的大小.

in Grid layout mode

按視窗的左上方可以切換兩種模式

切換layout 模式

在Grid layout mode 時Grid的Column及Row的上左方會有如下三種圖案, 代表Column或Row計算大小的方式

Star Sized Pixel sized Auto sized

在選取控制項除了四邊的控點之外也會有與邊界距離的實線或虛線, 實線代表HorizontalAlignment, VerticalAlignment屬性的對齊關係, 上頭的數字則是Margin屬性的數字. 你可以發現實線上頭有數字, 虛線上頭沒有數字代表Margin的那個相對邊值為零.

7

2008年8月23日 星期六

VB 的Windows 應用程式程式架構

想要使用VB提供的應用程式架構, 但又想自己控制初始執行表單的順序...

這是上課時同學問的問題.

他的問題細節是這樣的, 要先有一個登入視窗, 通過登入流程之後, 顯示SplashScreen 之後才是MainForm.

過去我們會將這程序寫在Sub Main, 然後專案的"啟動表單"指定成為Sub Main.

但是在Visual Studio的Visual Basic專案, 若要指定Sub Main必須將"啟用應用程式架構"停用, 這代表無法享用Visual Baisc提供的應用程式架構, 這個同學的需求中又需要用到這個架構, 該如何解決這問題呢?

測試了一下, 我的解決方案如下:

Step1.使用 "檢視應用程式事件"

1

Step2.在ApplicationEvents.vb 覆寫 OnInitialize 方法

Protected Overrides Function OnInitialize(ByVal commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean 

    LoginForm1.ShowDialog()

    If User.IsAuthenticated Then 
        Return MyBase.OnInitialize(commandLineArgs)

    End If

End Function


使用User.IsAuthenticated 檢查是否通過驗證, 如果通過驗證才繼續初始化(呼叫 MyBase.OnInitialize(commandLineArgs) ), 如果未呼叫MyBase.OnInitialize的話, Application不會繼續初始化, 應用程式就會自動結束.



完成!!



A1: 為什麼要覆寫OnInitialize 而不寫在Statup 事件?

Q1: 因為Statup事件已經啟動SplashScreen, 不符合要先Login 再進SplshScreen 的需求. 而且無法控制登入失敗要終止程式(無法呼叫Application.Exit方法)



A2: 怎麼寫LoginForm1的程式?

Q2: 以下步驟解說:


     step1: 加入新項目, 選取"登入表單"

     step2: 允許兩次登入失敗, 宣告變數記錄


Dim errorTry As Short = 0


    step3: 修改OK 按鈕的Click事件如下: (要Imports System.Security.Principal)


Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click  
    Dim roles() As String
    If Not CheckUser(UsernameTextBox.Text, PasswordTextBox.Text, roles) Then
        errorTry += 1
        If errorTry >= 3 Then
            Me.Close()
        End If
        Return
    End If
    Dim iden As New GenericIdentity(UsernameTextBox.Text)
    My.User.CurrentPrincipal = New GenericPrincipal(iden, roles)
    Me.Close()
End Sub

  在登入成功之後, 設定My.User.CurrentPrincipal, 就可以讓User.IsAuthenticated 回傳True.   



    step4: CheckUser 方法是寫檢查帳號密碼的程式, 請自行設計, 下列程式僅供參考.


Private Function CheckUser(ByVal Username As String, ByVal Password As String, ByRef Roles() As String) As Boolean  
    If String.IsNullOrEmpty(Username) Then
        Return False
    End If
    Roles = New String() {"Users"}
    Return True
End Function

2008年8月15日 星期五

ASP.NET 3.5 sp1 新增的 Dynamic Data網站

Visual Studio 2008 sp1 在建立ASP.NET 網站的範本中多了"Dynamic Data網站"Dynamic Data 網站範本

又是一個令人 "哇!" 的功能, 簡單來說, 建立網站之後, 他只需要做三個步驟就可以完成網頁資料表的"新刪修"功能.

1. 加入新項目 "Link to SQL 類別"

選擇Link to SQL

2.伺服器總管連到Northwind資料庫, 並將必要的資料表拖拉到Link to SQL 類別的設計視窗.

設計Link to SQL

3.接著修改Global.asax的程式碼, 移去下面這行程式的註解, 並修改"YourDataContextType"為第一步驟加入的Link to SQL的類別名稱, 以及設定ScaffoldAllTables 屬性為True即可.

model.RegisterContext(GetType(DataClassesDataContext), _
                      New ContextConfiguration() With {.ScaffoldAllTables = True})

執行結果:

執行結果1 - 資料表名稱

點選"Employees"之後

執行結果2 - Employees List

點"詳細資料"

執行結果3 - Employees Detail

 

相關參考: Your First Scaffold, and What Is Dynamic Data-

2008年8月12日 星期二

Visual Studio 2008 SP1 開放下載了

Visual Studio 2008 SP1 已經於8/11開放下載了.

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-tw&FamilyID=fbee1648-7106-44a7-9649-6d9f6d58056e

注意事項:

  1. 最好先完成作業系統的Windows Update再安裝VS2008 SP1.
  2. 如果是Vista 請先關閉"Windows 資訊看板"
  3. 若之前曾安裝一些Beta 版的相關軟體, 請先移除.
  4. 如果還是裝不起來, 請先閱讀上面Link頁中的ReadMe

2008年5月31日 星期六

DataGridView - 加入ComboBox 欄位

DataGridView 支援多種欄位控制項, 包含CheckedBox, ComboBox, Image ... 等. 可以被加入DataGridView的欄位物件必須是DataGridViewColumn 類別的延伸類別, .NET 內建DataGridViewComboBoxColumn, 即可呈現ComboBox 的效果. 屬性列表:

  • DataPropertyName: 繫結到DataGridView 的欄位
  • DataSource: 下拉內容的資料來源
  • DisplayMember: 顯示的欄位
  • ValueMember: 不會顯示的欄位
下面這段範例是說明如何在產品資料表中包含一個分類的下拉選項, DataGridViewComboBoxColumn 必須與Categories 進行資料繫結.
        Dim combo As New DataGridViewComboBoxColumn
combo.DataSource = CategoriesBindingSource
combo.DataPropertyName = "CategoryID"
combo.DisplayMember = "CategoryName"
combo.ValueMember = "CategoryID"

ProductsDataGridView.Columns.Insert(0, combo)



執行結果如下:


ComboBox

2008年5月23日 星期五

DataGridView - Row的條件格式化

上一篇是針對儲存格的條件格式化, 這一篇是針對資料記錄, 例如, 檢查庫存量小於10時, 將整筆記錄以紅色顯示.
DataGridView在進行Row的繪制流程時會觸發兩個事件, 分別是RowPrePaint及RowPostPaint, 這裡是要在處理完Row的繪製動作之後, 再將每個儲存格背景色改為紅色, 所以是在RowPostPaint事件處理.

使用e.RowIndex取得DataGridViewRow物件,取出DataGridViewRow物件後, 經由DataBoundItem屬性取得該筆記錄,
然後判斷記錄欄位是否符合條件, 若符合條件, 修改該記錄的每個儲存格Style.BackColor屬性.

    Private Sub ProductsDataGridView_RowPostPaint(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewRowPostPaintEventArgs) Handles ProductsDataGridView.RowPostPaint
If e.RowIndex <= 0 Then
Return
End If
Dim row As DataRowView
row = CType(ProductsDataGridView.Rows(e.RowIndex).DataBoundItem, DataRowView)
If row("UnitsInStock") < 10 Then
For Each cell As DataGridViewCell In ProductsDataGridView.Rows(e.RowIndex).Cells
cell.Style.BackColor = Color.Red
Next
End If
End Sub


圖: 庫存量小於10, 整筆以紅色顯示.
01

DataGridView - 儲存格條件格式化

若要在DataGridView中提供儲存格的條件格式化, 例如, 檢查庫存量為零時, 儲存格背景色顯示為紅色.
這代表要對儲存格進行繪製作業, 可以在CellPainting 事件處理.

DataGridViewCellPaintingEventArgs 事件參數,提供ColumnIndex, RowIndex, Value, CellStyle, PaintBackground 等屬性, 可以利用這些屬性是處理引發事件的儲存格.

範例中我使用e.ColumnIndex 找到控制項對應的欄位名稱, 並確定是在進行記錄而不是標題處理(e.RowIndex >0), 才檢查儲存格是否為0. 透過CellStyle的BackColor 改變目前儲存格的背景色.

   Private Sub ProductsDataGridView_CellPainting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles ProductsDataGridView.CellPainting
If e.ColumnIndex <= 0 Then
Return
End If
Dim column As DataGridViewColumn
column = ProductsDataGridView.Columns(e.ColumnIndex)

If column.DataPropertyName = "UnitsInStock" AndAlso e.RowIndex > 0 _
AndAlso e.Value = 0 Then
e.CellStyle.BackColor = Color.Red
End If

End Sub


圖1: 庫存量為零的儲存格, 背景色為紅色.

01

2008年5月22日 星期四

DataGridView - 執行階段調整欄位順序

若要讓DataGridView 可以在執行階段調整欄位順序倒不是一件難事, 只要設定控制項的AllowUserToOrderColumns 屬性為True即可達到效果. 此屬性預設是False.

圖1: 拖拉QuantityPerUnit欄位
01

圖2:欄位調整後
02

2008年5月21日 星期三

DataGridView - 凍結欄位與記錄

DataGridView 是.NET Framework 2.0 新增的Windows Form 控制項, 這個控制項提供類似Excel 凍結欄位及記錄的功能.

DataGridViewColumn及DataGridViewRow皆有Frozen 屬性, 只要將這個屬性值設為True就可達到凍結的目的.

處理凍結時通常還會將 "分割線" 設為較粗的線條, 
DataGridViewColumn有DividerWidth屬性, DataGridViewRow有DividerHeight屬性, 分別將它們設為大於1的值就會有比較明顯的區隔效果.

例如, 在Form_Load 事件處理凍結效果:

ProductsDataGridView.Columns(1).Frozen = True   
ProductsDataGridView.Columns(1).DividerWidth = 3

ProductsDataGridView.Rows(1).Frozen = True
ProductsDataGridView.Rows(1).DividerHeight = 3


圖1: 凍結ProductName欄及第二筆記錄
凍結ProductName欄及第二筆記錄



圖2: 凍結效果的呈現
凍結效果的呈現

2008年5月8日 星期四

Visual Studio 2008的重構功能(1) – for C#

在程式寫完之後,重新審視程式可能會發現程式有很多地方需要最佳化。例如,類別中的公開變數需要封裝、變數名稱不合規範要修改、太多重複出現的程式可以提列為方法…等等。在你的程式碼需要做大手術時,工具有沒有提供重構(Refactor)功能就很重要了。重構功能在Visual Studio 2005的C#編輯器中首次出現,可惜的是Visual Basic編輯器的重構功能只有「重新命名」這一項(Visual Studio 2005及Visual Studio 2008皆是)。這篇文章將介紹重構(Refactor)功能。

什麼是重構?

重構(Reactor)是指在程式完成之後,在不變更外部行為的情況下修改程式碼內部的結構,以達到最佳化程式碼程序的目的。Visual Studio 2008的C#編輯器內含的重構功能包含以下項目:
  • 重新命名: 可以為變數、方法、命名空間、類別名稱…等多種類型的名稱重新命名,並且會將所有參考到這個名稱的程式一併修改,免除了修改名稱的後遺症。
  • 封裝欄位:熟知物件導向的朋友看到這四個字,應該就知道這是做什麼的了。它可以幫你將Public的欄位封裝成屬性及私有欄位。 擷取方法可以將選取的程式碼區段提出成為一個新的方法。
  • 擷取介面:可以從現有的類別或結構根據其成員產生一個新介面。
  • 重新排列:參數用來變更方法、索引子、Delegate的參數順序,同時會更新呼叫到此成員的程式參數順序。
  • 移除參數: 將方法、索引子、Delegate的參數移除。同時更新呼叫端的程式。
  • 將區域變數升級為參數: 名稱已經很清楚的表達用途了,可將方法、索引子、建構函式的區域變數升級為參數,並且更新其他呼叫端的程式。重新命名、重新排列參數、移除參數、將區域變數升級為參數等功能都會影響到其他呼叫端的程式,Visual Studio會進行多專案跨檔案的更新,同時為了預防自動更新所發生的錯誤,也提供了預覽變更的對話方塊以供確認。
詳全文...

2008年5月5日 星期一

Visual Basic 的表單列印功能

應用程式的資料若需要設計可輸出的報表,可以藉由Visual Studio開發工具所附的報表工具(Microsoft Report或Crystal Report)設計可輸出的報表。某些時候,使用者的需求是要將目前執行中的表單狀態輸出,而不是另外製作的報表格式。

對於Visual Basic的開發者來說,直接列印執行中的表單,並不是一件難事。Visual Studio 2008的Visual Basic語言Windows應用程式專案,可以在「工具箱」的「Visual Basic Power Packs」索引頁籤看到PrintForm控制項。控制項的名稱已經直接了當的介紹它的用途。

更多詳細內容, 請參考: http://www.delightpress.com.tw/article_c.aspx?article_id=36

Visual Basic 2008最佳實務講座內容勘誤-1

感謝讀者Jeffrey 回報書中錯誤, 以下是修正內容:
1.第6頁, 第12行
應為Visual Basic 2008, 而不是Visual Basic 2005
2.第56頁,練習中的Label1屬性應該要設定:
UseMnemonic=>False , ForeColor=>ButtonHighlight, 沒有FontColor屬性(筆誤).
3.第67頁, 第7題
答案應為B

2008年4月3日 星期四

2008年3月20日 星期四

.NET 可以算出農曆嗎?

答案, 還是Yes!!

.NET Framework (2.0以上)的類別庫中有一個TaiwanLunisolarCalendar 類別(參考: http://msdn2.microsoft.com/zh-tw/library/system.globalization.taiwanlunisolarcalendar.aspx)

這個類別的可看性就多囉!

它與一般的西曆及國曆是很不一樣的, 尤其可能有閏月. 要顯示完整的年月日, 至少要用到以下幾個方法:

  • GetSexagenaryYear
  • GetCelestialStem
  • GetTerrestrialBranch
  • GetMonth
  • GetLeapMonth
  • GetDayOfMonth

下列程式是完整的範例:

        Dim cal As New TaiwanLunisolarCalendar()
Dim now As Date = Date.Now.AddYears(-1)

Dim 天干 As String = "甲乙丙丁戊己庚辛壬癸"
Dim 地支 As String = "子丑寅卯辰巳午未申酉戌亥"

Dim lun60Year As Integer = cal.GetSexagenaryYear(now)
Dim 天干Year As Integer = cal.GetCelestialStem(lun60Year) - 1
Dim 地支Year As Integer = cal.GetTerrestrialBranch(lun60Year) - 1

Dim lunMonth As Integer = cal.GetMonth(now)
Dim leapMonth As Integer = cal.GetLeapMonth(cal.GetYear(now))

If leapMonth > 0 AndAlso lunMonth >= leapMonth Then
lunMonth -= 1
End If
Dim lunDay As Integer = cal.GetDayOfMonth(now)

MessageBox.Show(String.Format("農曆:{0}年{1}月{2}日", _
天干(天干Year) & 地支(地支Year), lunMonth, lunDay))

                TaiwanLunisolarCalendar cal =new TaiwanLunisolarCalendar()  ;
DateTime now = DateTime.Now.AddYears(-1) ;

String 天干= "0甲乙丙丁戊己庚辛壬癸" ;
String 地支= "0子丑寅卯辰巳午未申酉戌亥" ;

int lun60Year = cal.GetSexagenaryYear(now) ;
int 天干Year = cal.GetCelestialStem(lun60Year) ;
int 地支Year = cal.GetTerrestrialBranch(lun60Year) ;

int lunMonth = cal.GetMonth(now) ;
int leapMonth = cal.GetLeapMonth(cal.GetYear(now)) ;

if (leapMonth > 0 && lunMonth >= leapMonth )
{
lunMonth -= 1 ;
}
int lunDay = cal.GetDayOfMonth(now) ;

MessageBox.Show(String.Format("農曆:{0}年{1}月{2}日",
天干[天干Year].ToString() + 地支[地支Year].ToString(), lunMonth, lunDay));

以今天的日期(AddYears(-1))來執行, 得到的結果會是(去年的今天):
農曆:丁亥年2月2日

2008年3月19日 星期三

.NET 會算中華民國曆嗎?

答案是: Yes!!

.NET Framework (2.0以上)的類別庫中有一個 TaiwanCalendar (參考http://msdn2.microsoft.com/zh-tw/library/system.globalization.taiwancalendar.aspx)

不過, 台灣曆法與西曆只有差在紀元的計算, 例如, 西曆的2008年3月18日, 等於中華民國年的97年3月18日.

比較常用的會是它的GetYear方法, 如以下範例:

Dim cal As New TaiwanCalendar
Dim twYear As Integer = cal.GetYear(Date.Now)
MessageBox.Show("現在是中華民國:" & twYear & "年")
如果想直接讓應用程式使用中華民國曆法, 可以這樣寫:
Dim twCI As New CultureInfo("zh-TW")
twCI.DateTimeFormat.Calendar = New TaiwanCalendar()
Thread.CurrentThread.CurrentCulture = twCI
Console.WriteLine(Date.Now.ToLongDateString)

            CultureInfo twCI =new CultureInfo("zh-TW")  ;
twCI.DateTimeFormat.Calendar = new TaiwanCalendar() ;
Thread.CurrentThread.CurrentCulture = twCI ;
listBox1.Items.Add(DateTime.Now.ToLongDateString());

這樣將會印出如下格式的日期:
中華民國97年3月18日

2008年3月18日 星期二

書上架了!!

Visual Studio 2008 系列書終於上架囉!!

媽咪說只要讀完這些書我就是.net神童了!

小寶1

要從哪一本書開始呢?

 小寶2

2008年3月13日 星期四

3/18 確定會上架

出版社今天確定3/18會上架.

2008年3月11日 星期二

書的封面來了


書的封面終於出來了, 隨著書封面的遲到, 原本預計3/14出廠的書(內文早就進廠了)也將可能延遲到3/19才上架 (整個書系皆是).


唉~ 本來很期待這星期就可以拿到的 :< 已經預購的朋友們, 我們一起耐心等待吧!

2008年3月9日 星期日

Refactor! for Visual Basic 2008 的安裝說明

這本書的前一版(Visual Studio 2005 完全探索)有提到關於Refactor!的用法, 在[Visual Studio 2008最佳實務講座]已經完全移除. 並不是Visual Studio 2008的VB不支援, 而是書中新增太多VB重要而且必須講的內容. 在書本厚度(成本)等壓力下, Refactor!部份決定移除了. 作者將於此Blog陸續補上相關的應用及說明.

安裝需求

必須安裝Visual Studio 2008。

步驟1-下載

  1. 開啟IE,連接到http://msdn2.microsoft.com/zh-tw/vbasic/bb693327(en-us).aspx

    1

  2. 如圖點選Download now下載.

    (網頁會轉到另一個Page, 點選[ Download Your Copy Now >>]即可.)

  3. 下載完成後, 將取得[RefactorVB.NET-3.0.5.exe].

步驟2-安裝

  1. 執行[RefactorVB.NET-3.0.5.exe].
  2. 決定是否啟用Log記錄若需Log, 勾選[Enable Log], 然後點選【Install】按鈕.

    2

  3. 接著出現安裝精靈,點選【Next】按鈕。

    3

  4. 接著出現版權頁,選取「I accept the terms in the license agreement」,然後點選【Next】按鈕。

    4

  5. 在接下來的畫面上輸入「User Name」、「Organization」,點選【Next】按鈕。

    5

  6. 確定安裝位置,點選【Next】按鈕。

    6

  7. 決定是否事先執行MSDN說明的Namespace合併.

    若未勾選, Namespace合併作業將會在第一次開啟MSDN說明時進行.

    7

  8. 接著點選【Install】按鈕。開始進行安裝程序。

    8

  9. 安裝完成後出現如下畫面,點選【Finish】按鈕。

    9

  10. 開啟Visual Studio 2008在版權頁會看到已安裝的產品清單多了一個項目[Refactor! For Visual Studio]。代表安裝完成。

    10

2008年3月7日 星期五

Visual Basic的重構(Refactor)

這張圖是C#編輯器提供的Refactor功能.

可惜的是Visual Studio 2008的Visual Basic編輯器並沒提供Refactor的功能.

如果要說有, [重新命名]勉強算是. 其他的如"擷取方法", "封裝欄位", "擷取介面", "將區域變數提升至參數", "移除參數", "重新排列參數"...等這些項目在Visual Basic編輯器是了無蹤影.

Visual Basic的開發人員若想要享用Refactor的功能, 必須另外加裝Refactor! for Visual Basic 2008 .

下載及相關說明可以從http://msdn2.microsoft.com/en-us/vbasic/bb693327.aspx獲得.

2008年3月6日 星期四

Visual Basic 2008 上市了

Visual Basic 2008上市了,新增哪些功能?
安啦~ 肯定與Visual Basic 2005一樣,新增最大的功能就是讓人印象最深刻的「My」,「My」對於老Visual Basic來說真是親切無比,那些從Visual Basic 6到.NET之後找不到的功能,幾乎都可以在「My」裡面重見…。Visual Basic 2008是不是新增了個「I」,變的更加親切了呢?!

如果你抱著這樣的心態來看Visual Basic 2008,那就錯囉! 雖然這次的更新不像Visual Basic語言進入.NET世界當時發生那麼大的變革(Visual Basic 7新增物件導向的功能,弄的老Visual Basic們幾乎要重新學習! ),卻也會讓老Visual Basic們驚豔及花上一番功夫來學習它。

哪麼Visual Basic 2008到底新增什麼嚇人的功能呢?

話要從.NET 3.5開始說起,.NET 3.5引入一個新的資料查詢語言 -- Language Integrated Query(簡稱:LINQ,念音與Link相同)的功能。並且整合到Visual Basic以及C#語言,讓Visual Basic、C#擁有像SQL語法一般的資料查詢功能,可以對關聯式資料庫、DataSet、XML、物件集合…等資料來源進行類似SQL指令的查詢,它的語法:

From ... <Where ... Order By ... Select ... >

舉個簡單的例子:
Dim member() As String = {"Mary", "John", "Anita", "Lisa", "Andy", "Blue"}
Dim beginOfA = From name In member Where name Like "A*" Order By name
For Each s As String In beginOfA
Console.WriteLine(s)
Next

第一行是記錄人名的陣列. 第二行是使用LINQ查詢A開頭的人名. 第三行取得beginOfA查詢結果的陣列,使用For Each列出陣列內容. 得到的結果是:

Andy
Anita

沒錯LINQ語法是Visual Basic 2008(Visual Basic 9)這個版本新增的重要語法,別小看這個From … Where … 等句子,裡面可是包含很多重要的技術。如果你像我一樣迫不及待的窺探LINQ的世界,那麼你一定得先學學Visual Basic新增的觀念及語法:


  • 型別推論能力

  • Object Initializer/Object Initializer

  • 匿名型別

  • 擴充方法

  • Lambda Expressions

  • Query Expressions

  • Partial Methods

  • XML literals

  • Nullable types

  • Anonymous types

這些新功能大部份是為了讓LINQ語法使用起來更加的簡潔有力而設計的。

2008年3月4日 星期二

新書上市預告

Visual Studio 2008即將於今年的四月上市發表(其實已經在2008年元月可以下載到中文試用版)書也如預期的在二月中旬完成.

這本書主要的對象是針對想進入.NET程式開發世界的朋友們而寫的. 帶領讀者從最初淺的Visual Basic 語法到視窗應用程式的開發, 物件導向, 集合, 泛型以及Visual Basic 9最新的查詢運算式, 使用淺顯易懂的範例, 期望.NET的初學者能輕鬆的學會Visual Basic 2008.

書共分為三大部份,第一篇著重在語言基礎觀念的建立、第二篇著重在視窗的應用、第三篇則是從物件導向的角度探索Visual Basic 2008的語言世界。每個章節中設計了許多範例與實作,並於實作中設計重要觀念的問答題,期望讀者能藉此深入了解Visual Basic 2008以及工具Visual Studio 2008+的使用,進而學會使用Visual Basic 2008開發應用程式。

第一篇 語言基礎篇



在成為應用程式的程式設計師之前,你必須先學會如何使用程式語言,這一篇著重在Visual Basic程式語言的介紹與實作。讀者將從這章學到什麼是.NET Framework、Visual Studio 2008工具的使用以及Visual Basic程式語言。
  • 第1章:Visual Studio 2008概述
  • 第2章:Visual Basic 2008概述
  • 第3章:視窗輸入與輸出
  • 第4章:資料與變數
  • 第5章:流程控制
  • 第6章:迴圈
  • 第7章:程序與函式
  • 第8章:偵錯及例外處理
  • 第9章:類別與標準模組
  • 第10章:再探資料與變數


第二篇 視窗應用篇



在學會Visual Basic的基本語法之後,接下來我們再進一步的學習利用Visual Basic及Visual Studio開發工具開發Windows應用程式。在這第二篇中,你將學會如何建立Windows應用程式以及多種控制項的使用,同時你會了解如何開發一個可以存取資料庫的Windows應用程式以及報表。
  • 第11章 Windows表單
  • 第12章 Windows控制項
  • 第13章 資料庫存取
  • 第14章報表工具

第三篇 語言進階篇



Visual Basic是個物件導向的語言,如果你只會基本的Visual Basic語法,那只能說你會的不過是Visual Basic 6.0(Visual Basic 2008是產品名稱,它的版本代號是9.0 – Visual Basic 9.0)。第三篇我們將重點放在物件導向以及更多的進階議題,像是集合、泛型還有檔案系統。另外My命名空間也是Visual Basic獨有的特色,身為一個開發人員不可不會。同時在這篇中也加入了開發應用程式非常重要的議題 – 安裝與部署。
Visual Studio 2008預設對映的.NET版本是3.5,.NET 3.5新增一個非常重要的功能LINQ,也因此使得Visual Basic 2008新增許多新的語法,這些新增的語法我們將在最後一章中做介紹。
  • 第15章 物件導向
  • 第16章 集合
  • 第17章 泛型
  • 第18章 檔案系統
  • 第19章 Visual Basic的程式捷徑 -- My
  • 第20章 安裝與部署
  • 第21章 Visual Basic 2008新增功能

2008年1月25日 星期五

隨音樂起舞

保母有天帶小寶進一家店, 店中正放熱門音樂,
小寶竟隨音樂起舞. 今早試試...
哈, 真的吔! 太可愛了!!
過年時帶去街頭賣藝好了...哈~ 哈~


啊! 一早人家還沒開嗓...:p