2014年12月25日 星期四

WPF Binding (一) 控制項之間的繫結

  Binding 的作用是在於將資料顯示在控制項上,並且能夠根據來源或目的端的變更自動更新。要讓控制項能夠即時顯示各種資料來源的資料那麼就必要倚靠資料繫結的技術,資料繫結是利用 Binding 物件將控制項的某個屬性也就是目標屬性(Target Property)與資料關連在一起。資料來源可以是 XML 資料與 .NET CLR 物件,包含ADO.NET物件、其它Managed物件,或dynamic物件,而目標屬性必需是依存屬性(Dependency Property),如 TextBox 的 Text 屬性。以以下簡單例子來展示控制項之間的繫結。

  • xaml

<Window x:Class="SimpleDataBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="189" Width="223">
    <StackPanel Orientation="Vertical">
        <Label Height="30"
               Width="150"
               Margin="5"
               HorizontalAlignment="Left"
               Content="{Binding Path=Text,ElementName=textBox}"/>
        <TextBox x:Name="textBox"
                 Width="150"
                 Margin="5"
                 HorizontalAlignment="Left"/>
    </StackPanel>
</Window>

  繫結的語法是使用大括弧{},Binding 是標記擴充(Markup Extension)類別的名稱,ElementName 是來源名稱,Path 是要給於目標的屬性,要注意的是 ElementName 和 Path 之間要用逗號隔開。在程式碼中 Binding 的寫法如下,要注意的是在 xaml 頁面中,Label 要先給個 Name 後才可以做 Binding。



  • C#

<StackPanel Orientation="Vertical">
    <Label x:Name="label"
           Height="30"
           Width="150"
           Margin="5"
           HorizontalAlignment="Left"/>
    <TextBox x:Name="textBox"
             Width="150"
             Margin="5"
             HorizontalAlignment="Left"/>
</StackPanel>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Binding binding = new Binding();
       binding.Source = this.textBox;
        binding.Path = new PropertyPath("Text");
        this.label.SetBinding(Label.ContentProperty, binding);


        //this.label.SetBinding(Label.ContentProperty,new Binding("Text") { Source = this.textBox });
    }
}

  要完成目標物件的 Binding 之前,先建立個 Binding 物件,接下來依序設定 Source 來源及 Path,然後再加入目標物件方法 SetBinding(),程式碼註解的部份為目標物件的簡化操作。

2014年8月24日 星期日

NPOI 讀取 EXCEL 資料

DataTable 與 Excel 之間互轉

using System; 
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
using NPOI;
using NPOI.HPSF;
using NPOI.HSSF;
using NPOI.HSSF.UserModel;
using NPOI.POIFS;
using NPOI.Util;
 
public class DataTableRenderToExcel 
{
    public static Stream RenderDataTableToExcel(DataTable SourceTable)
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        MemoryStream ms = new MemoryStream();
        HSSFSheet sheet = workbook.CreateSheet();
        HSSFRow headerRow = sheet.CreateRow(0);
 
        // handling header.
        foreach (DataColumn column in SourceTable.Columns)
            headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);
 
        // handling value.
        int rowIndex = 1;
 
        foreach (DataRow row in SourceTable.Rows)
        {
            HSSFRow dataRow = sheet.CreateRow(rowIndex);
 
            foreach (DataColumn column in SourceTable.Columns)
            {
     dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
            }
 
            rowIndex++;
        }
 
        workbook.Write(ms);
        ms.Flush();
        ms.Position = 0;
 
        sheet = null;
        headerRow = null;
        workbook = null;
 
        return ms;
    }
 
    public static void RenderDataTableToExcel(DataTable SourceTable, string FileName)
    {
        MemoryStream ms = RenderDataTableToExcel(SourceTable) as MemoryStream;
        FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write);
        byte[] data = ms.ToArray();
 
        fs.Write(data, 0, data.Length);
        fs.Flush();
        fs.Close();
 
        data = null;
        ms = null;
        fs = null;
    }
 
    public static DataTable RenderDataTableFromExcel(Stream ExcelFileStream, string SheetName, int HeaderRowIndex)
    {
        HSSFWorkbook workbook = new HSSFWorkbook(ExcelFileStream);
        HSSFSheet sheet = workbook.GetSheet(SheetName);
 
        DataTable table = new DataTable();
 
        HSSFRow headerRow = sheet.GetRow(HeaderRowIndex);
        int cellCount = headerRow.LastCellNum;
 
        for (int i = headerRow.FirstCellNum; i < cellCount; i++)
        {
            DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
            table.Columns.Add(column);
        }
 
        int rowCount = sheet.LastRowNum;
 
        for (int i = (sheet.FirstRowNum + 1); i < sheet.LastRowNum; i++)
        {
            HSSFRow row = sheet.GetRow(i);
            DataRow dataRow = table.NewRow();
 
            for (int j = row.FirstCellNum; j < cellCount; j++)
                dataRow[j] = row.GetCell(j).ToString();
        }
 
        ExcelFileStream.Close();
        workbook = null;
        sheet = null;
        return table;
    }
 
    public static DataTable RenderDataTableFromExcel(Stream ExcelFileStream, int SheetIndex, int HeaderRowIndex)
    {
        HSSFWorkbook workbook = new HSSFWorkbook(ExcelFileStream);
        HSSFSheet sheet = workbook.GetSheetAt(SheetIndex);
 
        DataTable table = new DataTable();
 
        HSSFRow headerRow = sheet.GetRow(HeaderRowIndex);
        int cellCount = headerRow.LastCellNum;
 
        for (int i = headerRow.FirstCellNum; i < cellCount; i++)
        {
            DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
            table.Columns.Add(column);
        }
 
        int rowCount = sheet.LastRowNum;
 
        for (int i = (sheet.FirstRowNum + 1); i < sheet.LastRowNum; i++)
        {
            HSSFRow row = sheet.GetRow(i);
            DataRow dataRow = table.NewRow();
 
            for (int j = row.FirstCellNum; j < cellCount; j++)
            {
                if (row.GetCell(j) != null)
                    dataRow[j] = row.GetCell(j).ToString();
            }
 
            table.Rows.Add(dataRow);
        }
 
        ExcelFileStream.Close();
        workbook = null;
        sheet = null;
        return table;
    }
}

2014年8月8日 星期五

WPF 命名空間

x:Class
程式的事件與邏輯運算由 code-behind 完成。
<object x:Class=”namespace.classname”>
………………………………………
</object>

x:Name
唯一識別 xaml 定義的物件。 x:Name 與 Name 的效果是一樣的,但不能同時出現在同一元素。
<Button x:Name=”btn”…./>
<Button Name=”btn”…./>

x:Key
在 xaml 文件中,我們可以把很多需要多次使用的內容提取出來放在資源字典裡,需要使用這個資源的時候就將 Key 給檢索出來。
x:Key 的作用就是為資源貼上用於檢索的索引。在 WPF 中,幾乎每個元素都有自的 Resources 屬性。
<Window x:Class="Inventory.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="392" Width="533"
xmlns:d="clr-namespace:System;assembly=mscorlib"
ResizeMode="NoResize">
<Window.Resources>
<d:String x:Key="myString">Hello</d:String>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox Text="{StaticResource ResourceKey=myString}" Margin="5" />
<TextBox x:Name="txbBox" Margin="5"/>
<Button x:Name="btn" Content="ok" Click="btn_Click"/>
</StackPanel>
</Grid>
</Window>
為了在此例中可以讓我們使用 String 類別,我們需要引用類別庫 mscorlib.dll ,因此在 XAML 中,我們要加入 xmlns:sys=”clr-namespace:System;assembly=mscorlib”。sys 是自訂義的名稱空間。然後我們在 tag <Window.Resources> 中加入剛剛引用的名稱空間 <sys:String x:Key=”myString”> 並給 x:Key 一個值 “myString”。所以此例中的 TextBox 的 Text = Hello。