漫談WPF資料繫結 (2) – 繫結到多種資料來源

by Vivid 31. 五月 2011 19:08

WPF 資料繫結架構相當的有彈性,相對地也較為複雜,本文延續《漫談WPF資料繫結-使用Expression Blend 4》一文的內容,介紹如何使用Microsoft Expression Blend 4來設計WPF資料繫結程式。

WPF 資料繫結牽涉到兩個重要的屬性,一為Binding物件的Source屬性;一為繫結目標屬性。Binding 物件的來源物件可由以下屬性的定義來決定:ElementName、Source或RelativeSource屬性。而Path屬性是用來指定來源物件的屬性。

Binding物件包含一個Mode屬性,可以用來設定繫結的方向性。可以設定的值包括:

  • Default:使用目標屬性預設的模式,例如Label的Context屬性預設是OneWay。
  • OneTime:當應用程式啟動或資料載入時繫結一次,後續不再更新。
  • OneWay:當來源屬性變動時,更新目標屬性。
  • OneWayToSource:當目標屬性變動時,更新來源屬性。來源屬性變動時不更新目標屬性。
  • TwoWay:當目標屬性變動時,更新來源屬性。當來源屬性變動時,更新目標屬性。

繫結到Element

WPF可以繫結到一個XAML項目。假設目前WPF視窗上有一個Slider與TextBlock,您可以在Microsoft Expression Blend中,選取視窗中的TextBlock,從屬性視窗點選Text屬性後方的「Advanced options」選項->「Data Binding」,便會跳出「Create Data Binding」對話方塊。然後設定TextBlock的Text屬性繫結到Slider的Value屬性,請參考圖1所示。

clip_image002

圖 1:設定TextBlock的Text屬性繫結到Slider的Value屬性

Microsoft Expression Blend 4會自動產生以下XAML標籤設定繫結,利用ElementName描述要繫結到Slider:

<Grid x:Name = "LayoutRoot" Height = "131" Width = "263" >

<Slider x:Name = "slider" Height = "24" Margin = "12,26,0,0" VerticalAlignment = "Top" HorizontalAlignment = "Left" Width = "216" Maximum = "100" Minimum = "1" />

<TextBlock HorizontalAlignment = "Left" Height = "32" Margin = "87,74,0,0" TextWrapping = "Wrap" Text = "{Binding Value, ElementName=slider}" VerticalAlignment = "Top" Width = "48"/>

</Grid>

如此當你執行程式,移動Slider的刻度時,數值會自動呈現在TextBlock上,請參考圖2所示。

clip_image004

圖 2:繫結到Slider

繫結到物件

若要繫結到物件,且此物件是WPF或系統所提供的物件,您可以使用Binding 物件的Source屬性來指明來源物件,例如以下範例程式將TextBlock的Foreground屬性繫結到System.Windows. SystemColors的ActiveCaptionBrush屬性:

<Grid x:Name = "LayoutRoot" Height = "254" Width = "344">

<Slider x:Name = "slider" Height = "24" Margin = "12,26,0,0" VerticalAlignment = "Top"

HorizontalAlignment = "Left" Width = "216" Maximum = "100" Minimum = "1" />

<TextBlock Foreground = "{Binding Source={x:Static SystemColors.ActiveCaptionBrush}} "

HorizontalAlignment = "Left" Height = "57" Margin = "59,54,0,0" TextWrapping = "Wrap"

Text = "{Binding Value, ElementName=slider}" VerticalAlignment="Top" Width="109" FontSize="48"/>

</Grid>

因為Source繫結到ActiveCaptionBrush屬性,因此你不必再設定Path屬性。

繫結到邏輯資源(Logical Resource)

您也可以不用Source屬性而改用DataContext來設定資料繫結,特別是在有多個UI項目繫結到相同資料來源的情況下非常的有用。例如專案中若包含一個MyDataClass類別,其中有一個MyProperty屬性。

public class MyDataClass {

public string MyProperty { get; set; }

}

在Microsoft Expression Blend 4的繫結操作步驟為,在「Data」視窗->「Create Object Data Source」,選取MyDataClass建立資料來源,設定名稱為MyDataClassDataSource,請參考圖3所示。

clip_image006

圖 3:「Create Object Data Source」視窗。

Microsoft Expression Blend 4可以使用拖曳方式設定資料繫結。例如從工具箱拖曳一個TextBlock控制項到視窗設計畫面,然後從「Data」視窗將MyDataClass的MyProperty拖曳到TextBlock上方後放開,請參考圖4所示。Microsoft Expression Blend 4會自動為你建立資料繫結的語法。

clip_image008

圖 4:使用拖曳方式設定資料繫結。

為了測試繫結的結果,開啟XAML設計畫面,在Microsoft Expression Blend 4自動產生的<local:MyDataClass>標籤中設定「MyProperty="123"」賦予其初始值:

<local:MyDataClass MyProperty = "123" x:Key = "MyDataClassDataSource" d:IsDataSource = "True" />

目前XAML看起來如下,Grid控制項的DataContext屬性設定成key為MyDataClassDataSource的邏輯資源,而TextBlock的Text屬性則繫結到MyProperty屬性:

 

<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x  ="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local = "clr-namespace:wpfDatabinding3" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d"
    x:Class = "wpfDatabinding3.__BindToLogicalRes"
    x:Name = "Window" Title = "__BindToLogicalRes" Width = "640" Height = "480">
    <Window.Resources>
        <local:MyDataClass MyProperty = "123" x:Key = "MyDataClassDataSource" d:IsDataSource = "True" />
    </Window.Resources>
    <Grid x:Name = "LayoutRoot" DataContext = "{Binding Source={StaticResource MyDataClassDataSource}}"   >
        <TextBlock HorizontalAlignment = "Right" Height = "64" Margin = "0,80,80,0" TextWrapping = "Wrap" Text = "{Binding MyProperty}" VerticalAlignment = "Top" Width = "128"/>
    </Grid>
</Window>

 

RelativeSource

您也可以使用RelativeSource屬性以視覺樹(Visual Tree)項目的相對位置來建立資料繫結,通常在有指定Source的情況下使用。RelativeSource包含一個Mode屬性用來控管繫結的類型。RelativeSource的Mode屬性可設定的值包含:

  • FindAncestor:繫結到視覺樹(Visual Tree)項目的父代。通常搭配AncestorType與AncestorLevel屬性使用。
  • Self:繫結到目前項目。
  • TemplatedParent:繫結到ControlTemplate中的項目。
  • PreviousData:繫結到清單項目的前一個項目。

以下分別說明這幾種不同的Mode 的差異性。

RelativeSource Mode- FindAncestor繫結到父代

FindAncestor模式可以取繫結到目前項目的父代,例如Window中包含以下標籤將Mode設定為FindAncestor:

<Grid Tag = "This is Grid Data" x:Name = "LayoutRoot" >

<TextBlock Margin = "39,112,449,285" TextWrapping =" Wrap" Text = "{Binding Path=Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid, AncestorLevel=1}}"/>

</Grid>

AncestorType指定Source物件的型別,這個範例指定為Grid。AncestorLevel指定父代位於視覺樹的層次(Level),這個範例指定為表上一層。這個範例中透過繫結的設定TextBlock控制項會顯示出「This is Grid Data」文字。

RelativeSource Mode- Self繫結到自己

RelativeSource 的Mode設定成Self可以繫結到自己,例如以下標籤讓TextBlock的Height屬性繫結到Width屬性,如此寬度與高度便會相等。

<TextBlock Margin = "317,185,171,212" TextWrapping = "Wrap"

Width = "100" Height = "{Binding Path=Width, RelativeSource={RelativeSource Mode=Self}}" />

以上語法相當於以下使用ElementName的寫法:

<TextBlock Margin = "341,54,177,287" TextWrapping = "Wrap"

Width = "100" Height = "{Binding Path=Width, ElementName=txt}" Name="txt" />

RelativeSource Mode- TemplatedParent繫結到樣版

RelativeSource 的Mode設定成TemplatedParent可以讓你繫結到樣版,例如為Button設計一個ControlTemplate,樣版中使用Ellipse為按鈕定義一個圓型的外觀,將RelativeSource的Mode設定為TemplatedParent可以取得套用此樣版的按鈕之實體。ControlTemplate樣版如下所示:

<Window.Resources>
        <ControlTemplate x:Key = "myTemplate" TargetType = "Button">
            <Grid>
<Ellipse Fill = "{Binding Path=Background, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                <ContentPresenter HorizontalAlignment = "Center" VerticalAlignment = "Center" />
            </Grid>
        </ControlTemplate>
</Window.Resources>

Window中包含一個Button控制項如下,設定Template為上述的樣版:

<Button Template = "{StaticResource myTemplate}"

Background = "Blue" Content = "123" Height="23" HorizontalAlignment = "Left" Margin = "58,24,0,0" Name = "button1" VerticalAlignment="Top" Width="75" />

則樣版中的背景顏色會繫結到Button的Background 呈現藍色,效果如圖5所示:

clip_image010

圖 5:繫結到樣版

樣版可以改用更簡潔的TemplateBinding語法,例如將此範例樣版修改如下可以得到一樣地效果:

<ControlTemplate x:Key = "myTemplate" TargetType = "Button">

<Grid>

<Ellipse Fill = "{TemplateBinding Property=Background}" />

<ContentPresenter HorizontalAlignment = "Center" VerticalAlignment = "Center" />

</Grid>

</ControlTemplate>

RelativeSource Mode- PreviousData繫結到清單中前一項目

 

RelativeSource 的Mode設定成PreviousData允取您繫結到清單中前一項目,假設有一資料MyListDataClass類別如下,其中包含一個List集合存放10、20與30三個數值:

public class MyListDataClass {
        public MyListDataClass ( ) {
            data.Add ( 10 );
            data.Add ( 20 );
            data.Add ( 30 );
        }
        List<int> data = new List<int> ( );
        public List<int> Items { get { return data; } set { data = value; } }
    }

在Window.Resources中將MyListDataClass定義成資源,另外還包含一個資料樣版,利用RelativeSource設定繫結:

<Window.Resources>
        <local:MyListDataClass x:Key = "MyListDataClassDataSource" d:IsDataSource = "True"/>
        <DataTemplate x:Key = "Int32Template">
            <WrapPanel>
        <TextBlock Background = "Red" Text = "{Binding RelativeSource={RelativeSource PreviousData}}"/>
                <TextBlock Text = "{Binding Mode=OneWay}" />              
            </WrapPanel>
        </DataTemplate>
    </Window.Resources>

Window中包含一個Grid控制項,設定DataContext屬性指定資料來源為MyListDataClass物件,而ListBox控制項的ItemsSource屬性則繫結到MyListDataClass的Items屬性:

<Grid DataContext = "{Binding Source={StaticResource MyListDataClassDataSource}}">

<ListBox Height = "137" HorizontalAlignment = "Left" Margin = "49,62,0,0" x:Name="listBox1" VerticalAlignment = "Top" Width = "176" ItemTemplate = "{DynamicResource Int32Template}" ItemsSource = "{Binding Items}" />

</Grid>

此程式執行的效果如下,樣版中第一個TextBlock會繫結到集合中前一項目,此種方式方便用來比對資料,請參考圖6所示:

clip_image012

圖 6:繫結到清單前一項目。

繫結到集合

WPF資料繫結引擎可以讓你將控制項繫結到物件所成的集合。如果想要將一個Element繫結到一堆物件,你可以使用Item Control繫結到集合。Item Control預設提供多個屬性來支援繫結,包含:

  • DisplayMemberPath:設定要繫結的屬性。
  • ItemsSource:欲繫結之集合。預設ItemsSource屬性支援OneWay資料繫結。
  • ItemTemplate:用來建立集合中每個項目欲顯示的資料樣版。

假設有一MyListDataClass2資料類別包含字串所成之集合:

 

public class MyListDataClass2 {
        public MyListDataClass2 ( ) {
            data.Add ( new MyDataClass ( ) { MyProperty = "AAA" } );
            data.Add ( new MyDataClass ( ) { MyProperty = "BBB" } );
            data.Add ( new MyDataClass ( ) { MyProperty = "CCC" } );
        }
        List<MyDataClass> data = new List<MyDataClass> ( );
        public List<MyDataClass> Items { get { return data; } set { data = value; } }
    }

 

您可以在Microsoft Expression Blend 4的「Data」視窗->「Create Object Data Source」,選取MyDataClass2建立資料來源,設定名稱為MyListDataClass2DataSource。

接著將ListBox 控制項的ItemsSource繫結到MyListDataClass2DataSource物件的Items屬性。在Microsoft Expression Blend 4選取視窗中的ListBox,從屬性視窗點選Items屬性後方的「Advanced options」選項->「Data Binding」,便會跳出「Create Data Binding」對話方塊。然後設定ListBox的Items屬性繫結到MyListDataClass2的Items屬性,請參考圖7所示。

clip_image014

圖 7:設定ListBox的Items屬性繫結到MyListDataClass2的Items屬性。

然後設定ListBox 控制項DisplayMemberPath屬性為MyProperty,Microsoft Expression Blend 4會自動建立以下XAML標籤:

 

<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local = "clr-namespace:wpfDatabinding3" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" x:Class = "wpfDatabinding3._6_BindToList" Title = "_6_BindToList" Height = "300" Width = "300">
    <Window.Resources>
        <local:MyListDataClass2 x:Key = "MyListDataClass2DataSource" d:IsDataSource = "True"/>
    </Window.Resources>
    <Grid DataContext = "{Binding Source={StaticResource MyListDataClass2DataSource}}" >
        <ListBox Margin = "64,48,84,89" ItemsSource = "{Binding Items}" DisplayMemberPath = "MyProperty" />
    </Grid>
</Window>

 

 

繫結的效果如圖8所示:

clip_image016

圖 8:繫結到集合。

另一種比較常見的作法是不在資料來源類別寫死資料存取程式碼,例如改寫MyListDataClass2,新的MyListDataClass3類別建構函式中並不撰寫初始資料的程式碼:

public class MyListDataClass3 {
        public MyListDataClass3 ( ) {

        }
        List<MyDataClass> data = new List<MyDataClass> ( );
        public List<MyDataClass> Items { get { return data; } set { data = value; } }
    }

 

Window中ListBox控制項XAML定義如下,將ItemsSource屬性設定為{Binding},WPF會根據ItemsSource屬性或DataContext屬性的設定來找尋資料來源,ItemsSource屬性的優先權會高於DataContext屬性。

<ListBox x:Name = "listBox2" Margin = "120,8,100,0"

ItemsSource = "{Binding}" DisplayMemberPath = "MyProperty" Height = "80" VerticalAlignment = "Top" />

Window1程式如下,在建構函式初始化時,再利用程式建立集合中的資料,新增三個字串:

public partial class Window1 : Window {
       public Window1 ( ) {
           InitializeComponent ( );
           MyListDataClass3 data = new MyListDataClass3 ( );
           data.Items.Add ( new MyDataClass ( ) { MyProperty = "XXX" } );
           data.Items.Add ( new MyDataClass ( ) { MyProperty = "YYY" } );
           data.Items.Add ( new MyDataClass ( ) { MyProperty = "ZZZ" } );
           listBox2.DataContext = data.Items;
       }
   }

但這種做法在設計階段看不到繫結效果,要在程式執行時期才能看到繫結的結果。

繫結到集合-單一屬性

若要在WPF資料繫結應用程式下提供排序、資料篩選或資料分組功能,您可以利用Collection View。在WPF之中,所有集合都有一個預設的Collection View。您可以在XAML之中定義CollectionViewSource 項目繫結到集合,它代表一個CollectionView物件,以便於進行繫結。CollectionView包含一個記錄指標,指向目前存取的項目,讓您能夠瀏覽記錄。

例如有一個Label控制項欲繫結到清單方塊的資料來源 (MyListDataClass3):

<Label Content = "{Binding Path=MyProperty}" Height = "30" HorizontalAlignment = "Left" Margin = "12,117,0,0" Name = "label1" VerticalAlignment = "Top" Width = "89" />

於是我們在程式中設定Label控制項的DataContext屬性為MyListDataClass3的Items屬性:

label1.DataContext = data.Items;

但當執行時只有第一個項目會顯示在Label上,我們可以使用ICollectionView來瀏覽集合中的資料。例如以下兩個按鈕用來進行上一筆與下一筆資料瀏覽動作:

<Button Content = "Next" Height = "23" HorizontalAlignment = "Left" Margin = "103,162,0,0" Name = "button1" VerticalAlignment = "Top" Width = "75" Click = "button1_Click" />

<Button Content = "Prev" Height = "23" HorizontalAlignment = "Left" Margin = "12,162,0,0" Name = "button2" VerticalAlignment = "Top" Width = "75" Click = "button2_Click" />

因為將集合繫結到WPF Element,WPF會自動建立ICollectionView,因此在按鈕的Click事件中,可以加上以下程式碼,利用CollectionViewSource.GetDefaultView方法取得ICollectionView,然後利用MoveCurrentToPrevious方法移動指標到上一筆;利用MoveCurrentToNext方法移動指標到下一筆,這樣就可以進行資料瀏覽:

private void button2_Click ( object sender , RoutedEventArgs e ) {

ICollectionView cv = CollectionViewSource.GetDefaultView ( listBox2.ItemsSource );

      cv.MoveCurrentToPrevious ( );

}

private void button1_Click ( object sender , RoutedEventArgs e ) {

ICollectionView cv = CollectionViewSource.GetDefaultView ( listBox2.ItemsSource );

      cv.MoveCurrentToNext ( );

}

但因為Items Control繫結到整個集合(List),因此若要ListBox控制項的SelectedItem屬性能夠和目前正在瀏覽的項目同步,您可以設定ListBox的IsSynchronizedWithCurrentItem為true,例如以下程式碼所示:

listBox2.ItemsSource = data.Items;

listBox2.IsSynchronizedWithCurrentItem = true;

繫結到DataSet與DataTable

只要物件有實作IEnumerable介面,你便可以在WPF中進行資料繫結。常用的ADO.NET類別,諸如DataSet、DataTable或DataView物件都可以當作繫結的對象。假設目前Windows中包含一個ListBox控制項,其ItemsSource繫結到DataSet中Contacts DataTable:

<Grid Name="grid1">

<ListBox Height = "100" ItemsSource = "{Binding Path=Contacts}"

DisplayMemberPath = "FirstName" HorizontalAlignment = "Left"

Margin = "46,50,0,0" Name = "listBox1" VerticalAlignment = "Top" Width = "120" />

</Grid>

在Windows建構函式最後,利用ADO.NET物件建立SqlConnection連接到SQL Server AdventureWorks資料庫,透過SqlDataAdapter讀取出資料,加到DataSet 之中。最後將Grid控制項的DataContext屬性設定為DataSet物件變數:

 

public partial class _7_BindToDataSet : Window {
        DataSet contacts = new DataSet ( );
        public _7_BindToDataSet ( ) {
            InitializeComponent ( );
            using ( SqlConnection connection = new SqlConnection
                ( @"Server=.\SQLExpress;Database=AdventureWorks; Integrated Security=SSPI" ) ) {
                SqlDataAdapter da = new SqlDataAdapter (
                     "SELECT ContactID, FirstName, LastName FROM Person.Contact" ,
                    connection );
                da.Fill ( contacts , "Contacts" );
                grid1.DataContext = contacts;
            }
        }
    }

 

您也可以讓控制項繫結到DataTable中的DataColumn,例如以下語法將TextBlock控制項的Text屬性繫結到Contacts DataTable中LastName的DataColumn:

<TextBlock

Text="{Binding Path=Contacts/LastName}"

Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBlock1" VerticalAlignment="Top" />

使用ObjectDataProvider繫結

為了讓繫結動作更為方便,WPF提供一個ObjectDataProvider物件,可以讓你將WPF Element繫結到物件的方法(Method)回傳值。若有一資料類別如下,包含一個GetData方法,此方法會回傳一個List集合,集合中包含MyDataClass物件:

 

public class MyListDataClass4 {
        public MyListDataClass4 ( ) {
            data.Add ( new MyDataClass ( ) { MyProperty = "AAA" } );
            data.Add ( new MyDataClass ( ) { MyProperty = "BBB" } );
            data.Add ( new MyDataClass ( ) { MyProperty = "CCC" } );           
        }
        List<MyDataClass> data = new List<MyDataClass> ( );
        public List<MyDataClass> GetData ( ){return data;}
    }

 

 

您可以將ObjectDataProvider定義為邏輯資源,設定其ObjectType為資料類別型別,設定MethodName為GetData方法:

<Window x:Class = "wpfDatabinding3._8_BindToObjectDataProvider"
        xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
        Title = "_8_BindToObjectDataProvider" Height = "300" Width = "300"
        xmlns:local = "clr-namespace:wpfDatabinding3"
        >
    <Window.Resources>
        <ObjectDataProvider x:Key = "myProvider" ObjectType = "{x:Type local:MyListDataClass4}"
                            MethodName = "GetData" />
    </Window.Resources>
    <Grid>
        <ListBox
            DisplayMemberPath = "MyProperty"
            ItemsSource = "{Binding Source={StaticResource myProvider}}"
            Height = "100" HorizontalAlignment = "Left" Margin="82,64,0,0"
                              Name = "listBox1" VerticalAlignment = "Top" Width="120" />
    </Grid>
</Window>

使用XmlDataProvider繫結

XmlDataProvider可以應用在XML文件的繫結,您還可以利用Binding物件的XPath屬性來設定XPath查詢,選取XML文件中的節點來設定繫結。假設一個XAML片段如下,在StackPanel中定義一個XmlDataProvider內嵌一份XML文件:

<StackPanel>
        <StackPanel.Resources>
            <XmlDataProvider x:Key = "BooksLibrary" XPath = "BooksLibrary/Books">
                <x:XData>
                    <BooksLibrary xmlns="">
                        <Books>
                            <Book ISBN = "1-1223-0562-9" >
                                <Title>快快樂樂學.NET </Title>
                                <ListPrice> 340 </ListPrice>
                            </Book>
                            <Book ISBN = "0-3425-543-9" >
                                <Title>快快樂樂學C# </Title>
                                <ListPrice> 457 </ListPrice>
                            </Book>
                            <Book ISBN = "0-8632-753-2" >
                                <Title>快快樂樂學WPF </Title>
                                <ListPrice> 532 </ListPrice>
                            </Book>
                        </Books>
                    </BooksLibrary>
                </x:XData>
            </XmlDataProvider>
        </StackPanel.Resources>
        <ListBox >
            <ListBox.ItemsSource>
                <Binding Source = "{StaticResource BooksLibrary}"  XPath = "Book"/>
            </ListBox.ItemsSource>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text = "{Binding XPath=Title}" >                  
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>

ListBox控制項可以直接和XML文件透過Binding物件建立繫結。範例中利用XPath查詢來進行資料繫結的資料篩選動作,讓ListBox控制項繫結到Book標籤。特別要注意,若在內籤XML的XAML標籤中,要套用XPath查詢,必需將XML資料的根節點之xmlns設定為空字串,這樣可以避免其繼承System.Windows命名空間。

總結

如果資料來源的集合實作了IList介面,則CollectionViewSource.GetDefaultView方法會回傳ListCollectionView物件;如果資料來源的集合實作了IBindingList介面,則CollectionViewSource.GetDefaultView方法會回傳BindingListCollectionView物件。如果資料來源的集合實作了IEnumerable介面,則CollectionViewSource.GetDefaultView方法會回傳CollectionView物件。

 
   

Tags:

Expression Blend | WPF | 許薰尹Vivid Hsu | .NET Magazine國際中文電子雜誌

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List