달력

12

« 2007/12 »

  •  
  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 30
  • 31
  •  
  •  
  •  
  •  
  •  
2007/12/17 18:32

세상은 변해가는 것. Thinking2007/12/17 18:32


사용자 삽입 이미지
세상은 변했다.
어쩌면 진작에 변했을 수도 있다.

변화는 개인에게 100%순도를 자랑하는 청렴함을 요구하고 있다.

어찌보면 너무나 당연한 것일 수 있다.

당신이 머지않은 미래에 큰 성공을 꿈꾸고 있다면

그 요구에 순응해야 성공을 바라볼 수 있을 것이다.

'Thinking' 카테고리의 다른 글

little Star-The Elegants 1958  (0) 2007/12/28
개발을 하다보면...  (0) 2007/12/23
세상은 변해가는 것.  (0) 2007/12/17
interrupt time  (0) 2007/12/11
영화 선샤인을 본 후...  (0) 2007/12/11
돈이 세상의 전부는 아닙니다.  (0) 2007/12/11
Posted by -세티-
2007/12/17 10:31

Work Breakdown Structure (WBS) General Tech.2007/12/17 10:31



Work Breakdown Structure (WBS)

Click Here to View Video on YouTube5-Steps to Project Success

Download this Free Video (Same as above) (9MB file)

RIGHT Click & Save Target As: "5-Steps to Project Success - Seriously_v1.1"

You have permission to freely copy and distribute this video.

Introduction to the WBS

A Work Breakdown Structure is a results-oriented family tree that captures all the work of a project in an organized way.  It is often portrayed graphically as a hierarchical tree, however, it can also be a tabular list of "element" categories and tasks or the indented task list that appears in your Gantt chart schedule.  As a very simple example, Figure 1 shows a WBS for a hypothetical banquet.

pm_wbs_banquet.gif (9507 bytes)

Figure 1

Large, complex projects are organized and comprehended by breaking them into progressively smaller pieces until they are a collection of defined "work packages" that may include a number of tasks.  A $1,000,000,000 project is simply a lot of $50,000 projects joined together. The Work Breakdown Structure (WBS) is used to provide the framework for organizing and managing the work.

In planning a project, it is normal to find oneself momentarily overwhelmed and confused, when one begins to grasp the details and scope of even a modest size project.  This results from one person trying to understand the details of work that will be performed by a number of people over a period of time.  The way to get beyond being overwhelmed and confused is to to break the project into pieces, organize the pieces in a logical way using a WBS, and then get help from the rest of your project team.  

The psychologists say our brains can normally comprehend around 7-9 items simultaneously.  A project with thousands or even dozens of tasks goes way over our ability to grasp all at once.  The solution is to divide and conquer.  The WBS helps break thousands of tasks into chunks that we can understand and assimilate.   Preparing and understanding a WBS for your project is a big step towards managing and mastering its inherent complexity. 

The WBS is commonly used at the beginning of a project for defining project scope, organizing Gantt schedules and estimating costs.  It lives on, throughout the project, in the project schedule and often is the main path for reporting project costs.  On larger projects, the WBS may be used throughout the project to identify and track work packages, to organize data for Earned Value Management (EVM) reporting, for tracking deliverables, etc.

History of the WBS

The WBS was initially developed by the U.S. defense establishment, and it is described in Military Standard (MIL-STD) 881B (25 Mar 93) as follows: "A work breakdown structure is a product-oriented family tree composed of hardware, software, services, data and facilities .... [it] displays and defines the product(s) to be developed and/or produced and relates the elements of work to be accomplished to each other and to the end product(s)."

It requires some mental discipline to develop a product-oriented or deliverable-oriented grouping of project elements adding up to comprise the entire project scope. Intuitively, we tend to start out with a task-oriented approach. This is OK for very small projects where extensive project management controls will not be used. The task-oriented approach is easy to understand, because we can easily think of projects as collection of tasks. A task-oriented WBS can be developed by beginning with a simple "to-do" list and then clustering the items in a logical way. The logical theme could be project phases, functional areas, or major end-products.

If your organization will be collecting historical data to form a cost database, you should try to select a standard approach consistent with the organization’s long term data collection needs.

A sample WBS is shown in the figure below:

WBS Format for System Development Projects

Additional level 2 elements not shown here might include development environment support, logistics and training, and installation and startup.   This next link will take you to a skeleton sample WBS for a software and hardware system development project, and you can also download a zipped version of the corresponding MS-Project 2002 (.mpp) file.

A WBS for a large project will have multiple levels of detail, and the lowest WBS element will be linked to functional area cost accounts that are made up of individual work packages. Whether you need three levels or seven, work packages should add up through each WBS level to form the project total.

Product or Process Oriented?

The WBS was initially defined as a product oriented family tree, however subsequent definitions have introduced more flexibility -- so a WBS can also be deliverable or process oriented.  Your WBS can be built on nouns or verbs.  If the results of your project are primarily verbs, then a verb based or process based WBS may make more sense.  If your WBS is to be product or deliverable oriented, then you can start by thinking of the WBS as a parts list for the ultimate end-items of your project.  This link will give a simple illustration of a product or process based WBS orientation.  These differences are not shown to tell you what is the right way for your project, but just to familiarize you with the distinctions, so you can think about them and choose what's best for your project.

WBS Numbering

WBS elements are usually numbered, and the numbering system may be arranged any way you choose. The conventional numbering system is shown in the figure. The shaded box shown in the above slide could be numbered 1.2.2.3, which would tell you it was in the second box in level 2, the second box in level 3, and the third box in level 4.

WBS Dictionary

If a WBS is extensive and if the category content is not obvious to the project team members, it may be useful to write a WBS dictionary. The WBS dictionary describes what is in each WBS element, and it may also say what is not in an element, if that is unclear. Here is a sample of a WBS dictionary description:

WBS Element 1.5.4.5. - Systems Integration Test Equipment Planning - This element includes the effort to identify requirements and specify types and quantities of test equipment needed to support the System Integration and Test process. It does not include the design or procurement of such equipment, which is covered in Element 1.5.4.6.

Mapping WBS for Cost Management

In a product-oriented WBS, functional categories of work may form "cost accounts" within a WBS element. Cost account managers are responsible for a functional area’s contribution to a WBS element. Cost accounts from several departments or functions may combine into one WBS element.

Internal department planning for a cost account will be made up of individual work packages. A work package will typically have its own budget and schedule. Work packages should be small enough to be executed by individuals or small groups in a single department, and they should be of relatively short schedule duration. A small project might define a maximum work package size as two weeks of effort. Larger projects will assemble larger work packages that can be appropriately managed and controlled.

The project manager will have to decide to what degree employment of various details of WBS implementation will benefit the efficient management of the project. On a very small project, a formal WBS may serve no useful purpose, but it can become valuable if project size or complexity start to increase.

As an organization’s project management environment matures, or as larger size and complexity are encountered, application of the WBS concept can evolve from an ad hoc list of tasks, to time-phased activity lists, task lists clustered by project deliverables and services, or an end-product focused WBS fed by cost accounts and work packages.

If you are using MS-Project or a similar project management software application, you may encounter the WBS as a vertical list with indents to show structure. This will be compatible with the Gantt View data entry screens. While some software packages provide a separate WBS view, you could prepare your WBS in the vertical format using a word processor, and then cut and paste your WBS into your project management software package.

Program and Contract WBSs

A top-level WBS for a large program is sometimes called a Program WBS (PWBS) or Program Summary WBS (PSWBS). If a project involves several organizational participants or contractors, guidance for one contractor can be provided in a Contract WBS (CWBS). The project manager may provide a high-level CWBS for each developer, perhaps to level 2 or level 3.  The developer will then fill in the details of lower WBS levels to reflect the work to be accomplished and the data flow in that organization.

Organizational Standards

Your organization may want to decide on a standard WBS format or group of formats, use these across all projects, and communicate definitions widely so everyone will be speaking the same language. This can save re-learning project lessons and can lay the groundwork for successful data gathering to aid future cost estimates.

WBS Implementation

When you set up a project WBS, think about how you will be using it later in the project. Try to consider how you will organize the WBS, schedule format, manager assignments, and charge numbers, in your early project planning.  These days, the WBS in smaller projects ends up automatically being the indent structure in your Gantt schedule, so pay attention to those indents, and make sure that is the WBS you want for rolling up costs in your project, especially if you will be using EVM. It will be helpful if you can map the charge numbers, managers, and task groups to each other. This will help you track costs and progress for each manager. If your project schedule will on MS-Project, you may want to insert "text" columns into your schedule (Gantt View) for project charge numbers and manager names.

If your project charge numbers cannot be linked to groups of tasks assigned to specific managers, you will have no way to provide performance measurement feedback to managers.

Some project management environments have definite conventions for grouping items in a WBS. The best method is to have a WBS that works for your particular project environment. The WBS should be designed with consideration for its eventual uses. Your WBS design should try to achieve certain goals:

  • Be compatible with how the work will be done and how costs and schedules will be managed,

  • Give visibility to important or risky work efforts,

  • Allow mapping of requirements, plans, testing, and deliverables,

  • Foster clear ownership by managers and task leaders,

  • Provide data for performance measurement and historical databases, and

  • Make sense to the workers and accountants.

There are usually many ways to design a WBS for a particular project, and there are sometimes as many views as people in the process.   Experience teaches that everyone takes a slightly different slice of the apple, so make sure WBS arguments seeking metaphysical certainty are quickly brought to closure.  Simple practicality combined with enlightened trial and error usually is the best approach. 

Generating a WBS from Microsoft Project

There is a third-party add-on software application for MS-Project called WBS Chart Pro that will convert your Gantt chart task list with indents into a standard WBS graphic in a few clicks.   You can also use this application to create a WBS and transfer it back MSP.  I have found this software very valuable in organizing project work into a WBS, reviewing the scope of proposed projects, and helping managers visualize the WBS implicit in their MS-Project schedules.

PMI Practice Guide for WBS

The Project Management Institute (PMI) has a document, Project Management Institute Practice Standard for Work Breakdown Structures, that provides examples of WBS formats commonly used in several different project areas, construction, defense, etc.  From the PMI Web site, upper right corner, click on Publications & Information Resources, then on Bookstore.  Key word search for Work Breakdown Structure will bring up this standard and other references.

?Copyright 1997, 2004 James R. Chapman, All rights reserved.

Document Version 2.3 last updated February 26, 2007

Return to: Project Home

TAG WBS
Posted by -세티-

CMMI(Capability Maturity Model Integration)
- 조직 프로세스를 보다 적절히 관리하기 위해 준수해야 할 지침을 체계화 한 것.
- 5단계의 프로세스 Maturity 레벨이 있다.

평가 대상 영역
- 소프트웨어 개발
- 시스템 개발
- 프로젝트 관리
- 리스크 관리
- 시스템 조달, IT 서비스
- 인적관리

레벨1은 매우 미숙하고 혼돈된 개발 프로세스이며, 레벨5는 매우 성숙한 고품질을 실현하는 개발 프로세스이다.
1998년 기준으로 소프트웨어 개발을 실시하는 조직의 75%가 레벨1 이라고 추정된다.

CMM 모델?
- 미국의 카네기 멜론 대학의 Sofrware Engineering Inistitute가 IT 개발 프로세스 관리 능력 향상을 위해
  미국방성의 자금 지원을 받은 프로젝트 이다.
- 1986년부터 연구하여 1991년 발표된 표준 모델이다.
- 소프트웨어 이외에도 적용되는 분야가 많다.
- CMMI는 CMM의 후속 모델이며, 소프트웨어와 시스템 기술의 프로세스 개선을 위한 통합모델이며, 2001년에 발표되었다.

CMMI 프로세스
- 조직의 프로세스 개선을 통한 소프트웨어 개발 과정에서의 비용, 품질, 일정 등 모든 것을 충족시키며, 특정 성숙도 레벨로 진입하기 위한 최소한의 기준 제시와 반드시 수행해야 할 활동들의 집합으로 프로세스 프레임워크의 성숙도 향상을 위한 모델이다.

- CMMI 모델의 각 프로세스 영역(Process Areas)의 특별 목적(specific goals, SP)와 공통 목적(generic goals, GG)의 달성정도를 측정
  (프로세스 개선 수준을 나타냄)

- CMMI는 조직의 SW 개발뿐만 아니라 시스템설계, 하드웨어, 운영 등 시스템통합(System Integration, SI) 사업 전반에 대한 프로세스를 평가하고 정의하는 방법인 SCAMPI(Standard CMMI Appraisal Method for Process Improvement)를 제공

- 특히 제품 또는 서비스의 개발, 획득, 유지보수하기 위한 조직의 공정 및 관리 능력을 향상시키기 위한 가이드를 제공과 이를 통해 프로세스 개선 시 필요한 목표와 체계의 제공이 가능


[소프트웨어 프로세스 성숙도 레벨 5단계]
레벨 1(Initial)
- 개인의 역량에 따라 프로젝트의 성공과 실패가 좌우, 소프트웨어 개발 프로세스는 거의 없는 상태를 의미
- 표준화된 프로세스 없이 구행결과 예측이 곤란한 조직

레벨 2(Managed)
- 프로세스 하에서 프로젝트가 통제되는 수준으로 조직은 프로세스에 대한 어느 정도의 훈련이 되었다고 볼 수있다.
- 일정이나 비용과 같은 관리 프로세스 중심
- 기존 유사 성공사례를 응용하여 반복적으로 사용
- 기본 프로세스 구축에 의해 프로젝트가 관리되고 있는 조직

레벨 3(Defined)
- 레벨 2에서는 프로젝트를 위한 프로세스가 존재한다면 레벨 3에서는 조직을 위한 표준 프로세스가 존재함.
- 모든 프로젝트는 조직의 프로세스를 가져다 상황에 맞게 조정하여 승인받아 사용한다.
- 세부 표준 프로세스가 있어 프로젝트가 통제되는 조직

레벨 4(Quantitatively Managed)
- 소프트웨어 프로세스와 소프트웨어 품질에 대한 정량적인 측정이 가능
- 조직은 프로세스 데이터베이스를 구축하여 각 프로젝트에서 측정된 결과를 일괄적으로 수집하고 분석하여 품질평가를 위한 기준으로 삼는다.
- 프로젝트 활동이 정략적으로 관리․통제되고 성과 예측이 가능한 조직

레벨 5(Optimizing)
- 이 레벨에서는 지속적인 개선에 치중한다.
- 조직적으로 최적화된 프로세스를 적용하여 다시 피드백을 받아 개선하는 상위 단계이다.
- 지속적인 개선활동이 정착화 되고 최적의 관리로 프로젝트가 수행되는 조직


CMM은 미국 카네기 멜론 대학의 소프트웨어 공학 연구소(Software Engineering Inistitute)
정부기관 계약시 기본적으로 레벨 3를 요구하는 수준이다.

[참고]
1. 위키디피아

TAG CMMI
Posted by -세티-
2007/12/17 10:29

ASP.NET MVC Framework (Part 1) General .NET2007/12/17 10:29

ScottGu's Blog에 올라온 ASP.NET MVC Framework에 대한 내용 입니다.

ScottGu's Blog: http://weblogs.asp.net/scottgu/archive/ ··· t-1.aspx

Posted by -세티-
2007/12/17 10:28

HttpWebRequest General .NET2007/12/17 10:28

using System;
using System.Text;
using System.Data;
using System.Net;
using System.IO;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class XXXX_PrintData : BasePage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        ViewWebPage();
    }

    public void ViewWebPage()
    {
        HttpWebRequest objWebRequest = null;
        HttpWebResponse objWebResponse = null;
        StreamReader objStreamReader = null;

        NetworkCredential networkCred = new NetworkCredential("", "");
        CredentialCache networkCache = new CredentialCache();

        string strUrl = "";

        objWebRequest = (HttpWebRequest)WebRequest.Create(strUrl);
        networkCache.Add(new Uri(strUrl), "Basic", networkCred);
        objWebRequest.Credentials = networkCred;
        objWebResponse = (HttpWebResponse)objWebRequest.GetResponse();
        objStreamReader = new StreamReader(objWebResponse.GetResponseStream(), Encoding.GetEncoding(949));

        string strLine = string.Empty;
        string strBody = string.Empty;
        while (objStreamReader.Peek() != -1)
        {
            strLine = objStreamReader.ReadLine();
            this.viewPrintTable.InnerHtml += strLine + "\r\n";
        }
    }

    private string Chr(int p)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    private void StreamReader(Stream stream, object p)
    {
        throw new Exception("The method or operation is not implemented.");
    }
}

'General .NET' 카테고리의 다른 글

12월 18일자 마이크로소프트 뉴스레터의 일부  (0) 2007/12/24
ASP.NET MVC Framework (Part 1)  (0) 2007/12/17
HttpWebRequest  (0) 2007/12/17
HttpWebRequest  (0) 2007/12/17
VSTO - Word Automation  (0) 2007/12/17
Socket Class  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:28

HttpWebRequest General .NET2007/12/17 10:28

출처:http://blogs.msdn.com/buckh/archive/2004/07/28/199706.aspx

Authentication in web services with HttpWebRequest

Hatteras has three tiers: client, middle, and data.  The middle tier is an ASP.NET web service on a Windows 2003 Server running IIS 6.  When the client (we use C# for both it and the middle tier) connects to the middle tier, it must authenticate with IIS 6.  Depending upon the IIS configuration, that may be negotiate, NTLM, Kerberos, basic, or digest authentication.  Here's a page on Internet Authentication in .NET.

NOTE:  The code below uses the .NET 2.0 framework (Visual Studio 2005).

In order to authenticate, the client must have credentials that the server recognizes as valid.  For Windows Integrated Authentication (comprising NTLM and Kerberos) using the current logged-on user, the client can use CredentialCache.DefaultCredentials.  Here's how it looks in code.

using System;
using System.IO;
using System.Net;

class Creds
{
    public static void Main(string[] args)
    {
        Uri uri = new Uri(args[0]);

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
        req.Credentials = CredentialCache.DefaultCredentials;

        // Get the response.
        using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
        {
            StreamReader sr = new StreamReader(res.GetResponseStream());
            Console.WriteLine(sr.ReadToEnd());
        }
    }
}

You can find that same type of sample code in MSDN.  However, it gets more interesting if you want to use basic or digest authentication or use credentials other than the current logged-on user.

One interesting fact is that the HttpWebRequest.Credentials property is of type ICredentials, but it only uses instances of NetworkCredential and CredentialCache.  If you implement ICredentials on your own class that is not one of those two classes, you can assign it to the Credentials property, but HttpWebRequest will silently ignore it.

To go further, we need to look at the CredentialCache class itself.  This class is used to hold a set of credentials that are associated with hosts and authentication types.  It has two static properties, one of which we used above, that are the "authentication credentials for the current security context in which the application is running," which means the logged-on user in our case.

The difference is very subtle.  The documentation for DefaultCredentials says, "The ICredentials instance returned by DefaultCredentials cannot be used to view the user name, password, or domain of the current security context."  The instance returned by DefaultNetworkCredentials, being new in .NET 2.0 and of type NetworkCredential, would presumably let you get the user name and domain, but it didn't work for me when I tried it with the following code (UserName returned an empty string).

Console.WriteLine("User name: " + CredentialCache.DefaultNetworkCredentials.UserName);

The NetworkCredential class implements both the ICredentials (NetworkCredential GetCredential(Uri uri, String authType)) and ICredentialsByHost (NetworkCredential GetCredential(String host, int port, String authType)) interfaces.  The ICredentialsByHost interface is new in .NET 2.0.

The CredentialCache class has methods that let you add, get, and remove credentials for particular hosts and authentication types.  Using this class, we can manually construct what setting req.Credentials = CredentialCache.DefaultCredentials accomplished in the original example.

        CredentialCache credCache = new CredentialCache();
        credCache.Add(new Uri("http://localhost"), "Negotiate",
                      CredentialCache.DefaultNetworkCredentials);
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
        req.Credentials = credCache;

The authentication type can also be explicitly specified as "NTLM" and "Kerberos" in separate calls to Add().  This page on authentication schemes explains using Negotiate as follows.

Negotiates with the client to determine the authentication scheme. If both client and server support Kerberos, it is used; otherwise NTLM is used.

Let's say you want to work with basic or digest authentication.  The documentation for CredentialsCache.DefaultCredentials and CredentialsCache.DefaultNetworkCredential says that neither will work with basic or digest.  If we add basic to credentials cache, we get a runtime exception.

        credCache.Add(new Uri("http://localhost"), "Basic",
                      CredentialCache.DefaultNetworkCredentials);

The exception is thrown by the Add() method.

Unhandled Exception: System.ArgumentException: Default credentials cannot be supplied 
for the Basic authentication scheme. Parameter name: authType at System.Net.CredentialCache.Add(Uri uriPrefix, String authType, NetworkCredential cred)

So, in order to use basic or digest, we must create a NetworkCredential object, which is also what we need to do in order to authenticate as some identity other than the logged-on user.  To do that, we create NetworkCredential object and add it to the CredentialCache as follows.

        credCache.Add(new Uri("http://localhost"), "Basic" /* or "Digest" */,
                      new NetworkCredential("me", "foo", "DOMAIN"));

Basic authentication sends the password across the wire in plain text.  That's okay for a secure connection, such as one using SSL, and for situations where you don't need much security.  Digest authentication hashes the password along with other data from the server before sending a response over the wire.  It's a significant step up from basic.

Now we need to have the user name and password to create the NetworkCredential object.  There are two parts to this.  First is prompting the user for the name and password.  The second is storing the information.  For prompting there is the Windows dialog that pops up any time you go to a web site that requires authentication.  That dialog includes a "Remember my password" checkbox.  I don't yet know what the managed API is for that.

To store and retrieve the information, there is the new managed DPAPI explained by Shawn Farkas in several blog postings.

[Update 3:44pm]  The Windows dialog used when IE prompts for name and password is created by the CredUIPromptForCredentials() function.  CredUIConfirmCredentials() is used to save credentials that authenticated successfully, if desired.  Duncan Mackenzie's MSDN article Using Credential Management in Windows XP and Windows Server 2003 explains how to use it from .NET.

[UPDATE 4/10/2006]  I updated the MSDN links that were broken.

Published Wednesday, July 28, 2004 11:50 AM by buckh
Filed under:

'General .NET' 카테고리의 다른 글

ASP.NET MVC Framework (Part 1)  (0) 2007/12/17
HttpWebRequest  (0) 2007/12/17
HttpWebRequest  (0) 2007/12/17
VSTO - Word Automation  (0) 2007/12/17
Socket Class  (0) 2007/12/17
DataTable.NewRow  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:27

VSTO - Word Automation General .NET2007/12/17 10:27

VSTO를 이용하여 워드에 데이터를 바인딩하고 관련 내용을 자동으로 출력해주는 코드 입니다.
이거 만드느라 시간 많이 들였죠...ㅎㅎ

#define DEBUG
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Configuration;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Configuration;

using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Word = Microsoft.Office.Interop.Word;
using Graph = Microsoft.Office.Interop.Graph;
using Office = Microsoft.Office.Core;
using Excel = Microsoft.Office.Tools.Excel;

public partial class CERS_Tot_MonthM : BasePage
{

    #region 변수선언부

    //날짜 변수
    string strYear      = string.Empty;
    string strMonth     = string.Empty;
    string strDay       = string.Empty;
    string nowDate      = string.Empty;

    //변수설정
    Word.Range          wrdRng1;
    Word.Range          wrdRng2;
    Word.Range          wrdRng3;
    Word.Range          wrdRng4;
    Word.Range          wrdRng5;
    Word.Range          wrdRng6;
    Word.Range          wrdRng7;

    Word._Application   oWord;
    Word._Document      oDoc;

    //Bookmarks 객체변수 선언
    object bookmark1    = null;
    object bookmark2    = null;
    object bookmark3    = null;
    object bookmark4    = null;
    object bookmark5    = null;
    object bookmark6    = null;
    object bookmark7    = null;

    object oMissing     = System.Reflection.Missing.Value;
    string mhtFileName  = string.Empty;
    string getFileName  = string.Empty;  //파일명(Doc, Mht)
    string getFilePath  = string.Empty;  //파일경로

    #endregion

    #region 페이지로드 이벤트메서드
    /// <summary>
    /// 페이지로드 이벤트메서드
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
        //페이지 타이틀 및 사이트네비게이션 설정
        this.lblTitle.Text          = "";
        this.spnSiteNavi.InnerHtml  = "";

        if (!IsPostBack)
        {
            //월
            string strMonth         = "00" + DateTime.Now.Month.ToString();

            //웹페이지에 날짜를 저장
            this.cal_Month.Value    = DateTime.Now.Year + "-" + strMonth.Substring((strMonth.Length - 2), 2);

            //iframe 활성화 여부
            ShowWordMht1.Visible    = false;

            //다운로드버튼 활성화 여부
            spnDownLoad.Visible     = true;

            //로그인 여부 확인 후 서브메뉴생성
            if (Session["sid"] != null)
            {
                if (Session["sid"].ToString() == CustId)
                {
                    //연구소 권한
                    if (CustGrade == "0") { }

                    //고객사 권한
                    if (CustGrade == "1")
                    {
                        MakeSubMenu();
                    }

                    //지점 권한
                    if (CustGrade == "2")
                    {
                        ShowMessageBox("XX권한으로 접근할 수 없습니다.", "");
                    }
                }
                else
                {
                    Response.Redirect("");
                }
            }
            else
            {
                Response.Redirect("");
            }

            spnDownLoad.InnerHtml = "[다운로드]";
        }

        this.hdnCustCode.Value = CustId;
        this.hdnFilePath.Value = Server.UrlEncode(WebConfigurationManager.AppSettings["XXXXXX"].ToString() + "\\Doc\\");
    }
    #endregion

    #region 디렉토리 관리 부분(CreateDirectory, CreateDoc, ShowMht)

    #region 디렉토리 생성 메서드
    /// <summary>
    /// 디렉토리 생성 메서드
    /// </summary>
    private static void CreateDirectory(string ParentDir, string ChildDir1, string ChildDir2)
    {
        if (!Directory.Exists(ParentDir))
        {
            DirectoryInfo di = Directory.CreateDirectory(ParentDir);

            if (!Directory.Exists(ChildDir1))
            {
                DirectoryInfo cdi = Directory.CreateDirectory(ChildDir1);
            }
            if (!Directory.Exists(ChildDir2))
            {
                DirectoryInfo cdi = Directory.CreateDirectory(ChildDir2);
            }
        }
        else
        {
            if (!Directory.Exists(ChildDir1))
            {
                DirectoryInfo cdi = Directory.CreateDirectory(ChildDir1);
            }
            if (!Directory.Exists(ChildDir2))
            {
                DirectoryInfo cdi = Directory.CreateDirectory(ChildDir2);
            }
        }
    }
    #endregion

    #region Doc 파일 생성메서드
    /// <summary>
    /// Doc파일 생성 메서드
    /// </summary>
    /// <param name="oMissing"></param>
    /// <param name="oWord"></param>
    /// <param name="oDoc"></param>
    /// <param name="bookmark2"></param>
    /// <param name="FileName"></param>
    /// <returns></returns>
    private void CreateDoc(ref object oMissing, Word._Application oWord, Word._Document oDoc, ref object FileName)
    {
        try
        {
            //bookmark의 Range를 할당
            wrdRng1                         = oDoc.Bookmarks.get_Item(ref bookmark1).Range;
            wrdRng2                         = oDoc.Bookmarks.get_Item(ref bookmark2).Range;
            wrdRng3                         = oDoc.Bookmarks.get_Item(ref bookmark3).Range;
            wrdRng4                         = oDoc.Bookmarks.get_Item(ref bookmark4).Range;
            wrdRng5                         = oDoc.Bookmarks.get_Item(ref bookmark5).Range;
            wrdRng6                         = oDoc.Bookmarks.get_Item(ref bookmark6).Range;
            wrdRng7                         = oDoc.Bookmarks.get_Item(ref bookmark7).Range;
           
            //표와 그래프 그리기
            DrawContent();

            //저장되는 문서 옵션
            object FileFormat               = Word.WdSaveFormat.wdFormatRTF;
            object LockComments             = false;
            object AddToRecentFiles         = true;
            object ReadOnlyRecommended      = false;
            object EmbedTrueTypeFonts       = false;
            object SaveNativePictureFormat  = true;
            object SaveFormsData            = true;
            object SaveAsAOCELetter         = false;
            object Encoding                 = false;
            object InsertLineBreaks         = false;
            object AllowSubstitutions       = false;
            object LineEnding               = Word.WdLineEndingType.wdCRLF;
            object AddBiDiMarks             = false;

            //저장하기
            oDoc.SaveAs(ref FileName, ref FileFormat, ref oMissing,
                    ref oMissing, ref AddToRecentFiles, ref oMissing,
                    ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing);
        }
        catch (Exception ex)
        {
            ShowMessageBox(ex.ToString(), "WIN");
        }
        finally
        {
            oWord.Quit(ref oMissing, ref oMissing, ref oMissing);
        }
    }
    #endregion

    #region Mht 파일 생성메서드
    /// <summary>
    /// Mth파일 생성
    /// </summary>
    /// <param name="oMissing"></param>
    /// <param name="oWord"></param>
    /// <param name="oDoc"></param>
    /// <param name="bookmark2"></param>
    /// <param name="FileName"></param>
    /// <returns></returns>
    private void ShowMht(ref object oMissing, Word._Application oWord, Word._Document oDoc, ref object FileName)
    {
        try
        {
            //bookmark의 Range를 할당
            wrdRng1                         = oDoc.Bookmarks.get_Item(ref bookmark1).Range;
            wrdRng2                         = oDoc.Bookmarks.get_Item(ref bookmark2).Range;
            wrdRng3                         = oDoc.Bookmarks.get_Item(ref bookmark3).Range;
            wrdRng4                         = oDoc.Bookmarks.get_Item(ref bookmark4).Range;
            wrdRng5                         = oDoc.Bookmarks.get_Item(ref bookmark5).Range;
            wrdRng6                         = oDoc.Bookmarks.get_Item(ref bookmark6).Range;
            wrdRng7                         = oDoc.Bookmarks.get_Item(ref bookmark7).Range;
           
            //표와 그래프 그리기
            DrawContent();
            //DrawGraph();

            //저장되는 문서 옵션
            object FileFormat               = Word.WdSaveFormat.wdFormatHTML;
            object LockComments             = false;
            object AddToRecentFiles         = true;
            object ReadOnlyRecommended      = false;
            object EmbedTrueTypeFonts       = false;
            object SaveNativePictureFormat  = true;
            object SaveFormsData            = true;
            object SaveAsAOCELetter         = false;
            object Encoding                 = false;
            object InsertLineBreaks         = false;
            object AllowSubstitutions       = false;
            object LineEnding               = Word.WdLineEndingType.wdCRLF;
            object AddBiDiMarks             = false;

            //저장하기
            oDoc.SaveAs(ref FileName, ref FileFormat, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing,
                    ref oMissing, ref oMissing, ref oMissing);
        }
        catch (Exception ex)
        {
            ShowMessageBox(ex.ToString(), "WIN");
        }
        finally
        {
            oWord.Quit(ref oMissing, ref oMissing, ref oMissing);
        }
    }
    #endregion

    #endregion

    #region 문서 생성 메서드
    /// <summary>
    /// 문서생성 메서드
    /// </summary>
    private void CreateDoc()
    {
        //iframe 활성화 여부
        this.ShowWordMht1.Visible   = true;

        //string strSdate             = "";
        object conffileName         = null;
        object fileName             = null;
        string confParentdir        = string.Empty;
        string strParentdir         = string.Empty;
        string strChildDir1         = string.Empty;     //Doc 파일 경로
        string strChildDir2         = string.Empty;     //Mht 파일 경로
        string sourceFileName1      = string.Empty;
        string sourceFileName2      = string.Empty;

        sourceFileName1             = WebConfigurationManager.AppSettings["XXXXX"].ToString();
        confParentdir               = WebConfigurationManager.AppSettings["XXXXX"].ToString();
        fileName                    = sourceFileName1;
        strParentdir                = confParentdir;
        strChildDir1                = strParentdir + "\\" + "Doc\\";
        strChildDir2                = strParentdir + "\\" + "Mht\\";

        //폴더 검사! 없으면 생성
        CreateDirectory(strParentdir, strChildDir1, strChildDir2);

        //파일명을 생성한다.
        object FileName1    = strChildDir1 + this.hdnCustCode.Value + "_" + this.cal_Month.Value.Replace("-", "") + ".doc";
        object FileName2    = strChildDir2 + this.hdnCustCode.Value + "_" + this.cal_Month.Value.Replace("-", "") + ".htm";
        mhtFileName         = this.hdnCustCode.Value + "_" + this.cal_Month.Value.Replace("-", "") + ".htm";

        //전역 파일경로 변수에 경로 할당
        getFilePath         = strChildDir1;

        //전역 파일이름 변수에 파일이름 할당
        getFileName         = (string)FileName1;

        //기존 Doc 파일 존재 여부를 검사
        try
        {
            oWord = (Word.Application)Server.CreateObject("Word.Application");
            oWord.Visible = true;
            oDoc = oWord.Documents.Add(ref fileName, ref oMissing, ref oMissing, ref oMissing);

            if (File.Exists(FileName1.ToString()))
            {
                File.Delete(FileName1.ToString());

                //Doc파일생성
                CreateDoc(ref oMissing, oWord, oDoc, ref FileName1);
                File.Delete(strChildDir1 + "Normal" + ".dot");
                File.Delete(strChildDir1 + "~Normal" + ".dot");
            }
            else
            {
                //Doc파일생성
                CreateDoc(ref oMissing, oWord, oDoc, ref FileName1);
                File.Delete(strChildDir1 + "Normal" + ".dot");
                File.Delete(strChildDir1 + "~Normal" + ".dot");
            }
        }
        catch (Exception ex)
        {
           
        }

        try
        {
            //mht 파일 존재 여부를 검사
            oWord = (Word.Application)Server.CreateObject("Word.Application");
            oWord.Visible = true;
            oDoc = oWord.Documents.Add(ref fileName, ref oMissing, ref oMissing, ref oMissing);

            if (File.Exists(FileName2.ToString()))
            {
                File.Delete(FileName2.ToString());
                Directory.Delete(strChildDir2 + mhtFileName.Replace("htm", "files"));

                //mht파일생성
                ShowMht(ref oMissing, oWord, oDoc, ref FileName2);
                File.Delete(strChildDir2 + "Normal" + ".dot");
                File.Delete(strChildDir2 + "~Normal" + ".dot");
            }
            else
            {
                //mht파일생성
                ShowMht(ref oMissing, oWord, oDoc, ref FileName2);
                File.Delete(strChildDir2 + "Normal" + ".dot");
                File.Delete(strChildDir2 + "~Normal" + ".dot");
            }
        }
        catch (Exception ex)
        {
           
        }
    }
    #endregion

    #region 문서 Content 생성(Draw Table, Draw Graph)

    #region Draw Content Method
    /// <summary>
    /// Draw Content Method
    /// </summary>
    private void DrawContent()
    {
        string nowFDate             = nowDate + "01";
        string nowTDate             = nowDate + "31";

        //오늘 날짜
        SqlParameter[] param        = new SqlParameter[3];
        param[0]                    = new SqlParameter("@CustId", CustId);
        param[1]                    = new SqlParameter("@FDate", nowFDate);
        param[2]                    = new SqlParameter("@TDate", nowTDate);

        SqlHelper dac               = new SqlHelper();
        DataSet ds                  = dac.ExecuteDataset(ConnectionString, CommandType.StoredProcedure, "[dbo].[XXXXX]", param);

        Word.Table tb1              = null;
        Word.Table tb2              = null;
        Word.Table tb3              = null;

        wrdRng1.Text                = this.cal_Month.Value.Substring(5,2);
        wrdRng2.Text                = ds.Tables[0].Rows[0][0].ToString();
        wrdRng3.Text                = ds.Tables[0].Rows[0][1].ToString();
        wrdRng4.Text                = this.cal_Month.Value.Substring(0, 4) +"년 " +this.cal_Month.Value.Substring(5, 2) + "월";

        tb1                         = ServiceTableList(ds, tb1);
        tb2                         = BugsTableList(ds, tb2);
        tb3                         = DivisionTableList(ds, tb3);

    }

    #region 테이블 1
    /// <summary>
    /// 테이블 1 생성 메서드
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="tb1"></param>
    /// <returns></returns>
    private Microsoft.Office.Interop.Word.Table ServiceTableList(DataSet ds, Word.Table tb1)
    {
        int tb1RowCnt               = ds.Tables[1].Rows.Count;
        int tb1ColCnt               = ds.Tables[1].Columns.Count;
       
        //테이블 존재여부 검사
        if (oDoc.Tables.Count != 0)
        {
            //테이블 생성하기
            //테이블 Header 셋팅
            tb1 = oDoc.Tables.Add(wrdRng5, 1, tb1ColCnt, ref oMissing, ref oMissing);
            tb1.Range.Tables[1].Rows[1].Cells[1].Range.Text = "Title1";
            tb1.Range.Tables[1].Rows[1].Cells[2].Range.Text = "Title2";
            tb1.Range.Tables[1].Rows[1].Cells[3].Range.Text = "Title3";
            tb1.Range.Tables[1].Rows[1].Cells[4].Range.Text = "Title4";
            tb1.Range.Tables[1].Rows[1].Cells[5].Range.Text = "Title5";
            tb1.Range.Tables[1].Rows[1].Cells[6].Range.Text = "Title6";
            tb1.Range.Tables[1].Rows[1].Cells[7].Range.Text = "Title7";
            tb1.Range.Tables[1].Rows[1].Cells[8].Range.Text = "Title8";

            //테이블 Cell 넓이, 스타일
            tb1.Range.Tables[1].Rows[1].Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[2].SetWidth(100, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[3].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[4].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[5].SetWidth(30, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[6].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[7].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
            tb1.Range.Tables[1].Rows[1].Cells[8].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
        }

        //데이터로우로 부터 테이블에 데이터를 추가한다.
        if (tb1.Range.Tables.Count > 0)
        {
            try
            {
                Microsoft.Office.Interop.Word.Row newRow = null;
                if (tb1RowCnt == 0)
                {
                    //newRow.Cells.Merge();
                }
                else
                {
                    for (int i = 0; i < tb1RowCnt; i++)
                    {
                        newRow = tb1.Range.Tables[1].Rows.Add(ref oMissing);
                        newRow.Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[2].SetWidth(100, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[3].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[4].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[5].SetWidth(30, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[6].SetWidth(60, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[7].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[8].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);

                        //루프를 돌면서 Cell에 내용을 출력
                        for (int j = 0; j < tb1ColCnt; j++)
                        {
                            int k = j + 1;
                            newRow.Cells[k].Range.Text = ds.Tables[1].Rows[i][j].ToString();
                        }
                    }
                }

                newRow = null;
            }
            catch (Exception ex)
            {
               
            }
        }

        //테이블 보더 스타일
        tb1.Borders.InsideLineStyle     = Word.WdLineStyle.wdLineStyleSingle;
        tb1.Borders.OutsideLineStyle    = Word.WdLineStyle.wdLineStyleSingle;

        return tb1;
    }
    #endregion

    #region 테이블 2
    /// <summary>
    /// 테이블2 생성메서드
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="tb2"></param>
    /// <returns></returns>
    private Microsoft.Office.Interop.Word.Table BugsTableList(DataSet ds, Microsoft.Office.Interop.Word.Table tb2)
    {
        int tb2RowCnt = ds.Tables[2].Rows.Count;
        int tb2ColCnt = ds.Tables[2].Columns.Count;

        //테이블 존재여부 검사
        if (oDoc.Tables.Count != 0)
        {
            //테이블 생성하기
            //테이블 Header 셋팅
            tb2 = oDoc.Tables.Add(wrdRng6, 1, tb2ColCnt, ref oMissing, ref oMissing);
            tb2.Range.Tables[1].Rows[1].Cells[1].Range.Text = "Title1";
            tb2.Range.Tables[1].Rows[1].Cells[2].Range.Text = "Title2";
            tb2.Range.Tables[1].Rows[1].Cells[3].Range.Text = "Title3";
            tb2.Range.Tables[1].Rows[1].Cells[4].Range.Text = "Title4";
            tb2.Range.Tables[1].Rows[1].Cells[5].Range.Text = "Title5";
            tb2.Range.Tables[1].Rows[1].Cells[6].Range.Text = "Title6";
            tb2.Range.Tables[1].Rows[1].Cells[7].Range.Text = "Title7";
            tb2.Range.Tables[1].Rows[1].Cells[8].Range.Text = "Title8";
            tb2.Range.Tables[1].Rows[1].Cells[9].Range.Text = "Title9";
            tb2.Range.Tables[1].Rows[1].Cells[10].Range.Text = "Title10";

            //테이블 Cell 넓이, 스타일
            tb2.Range.Tables[1].Rows[1].Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[2].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[3].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[4].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[5].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[6].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[7].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[8].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[9].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
            tb2.Range.Tables[1].Rows[1].Cells[10].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
        }

        //데이터로우로 부터 테이블에 데이터를 추가한다.
        if (tb2.Range.Tables.Count > 0)
        {
            try
            {
                Microsoft.Office.Interop.Word.Row newRow = null;
                if (tb2RowCnt == 0)
                {
                    newRow.Cells.Merge();
                }
                else
                {
                    for (int i = 0; i < tb2RowCnt; i++)
                    {
                        newRow = tb2.Range.Tables[1].Rows.Add(ref oMissing);
                        newRow.Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[2].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[3].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[4].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[5].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[6].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[7].SetWidth(45, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[8].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[9].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[10].SetWidth(50, Word.WdRulerStyle.wdAdjustNone);

                        //루프를 돌면서 Cell에 내용을 출력
                        for (int j = 0; j < tb2ColCnt; j++)
                        {
                            int k = j + 1;
                            newRow.Cells[k].Range.Text = ds.Tables[2].Rows[i][j].ToString();
                        }
                    }
                }
            }
            catch(Exception ex)
            {
           
            }
        }

        //테이블 보더 스타일
        tb2.Borders.InsideLineStyle     = Word.WdLineStyle.wdLineStyleSingle;
        tb2.Borders.OutsideLineStyle    = Word.WdLineStyle.wdLineStyleSingle;

        return tb2;
    }
    #endregion

    #region 테이블 3
    /// <summary>
    /// 테이블 3 생성 메서드
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="tb3"></param>
    /// <returns></returns>
    private Microsoft.Office.Interop.Word.Table DivisionTableList(DataSet ds, Word.Table tb3)
    {
        int tb3RowCnt = ds.Tables[3].Rows.Count;
        int tb3ColCnt = ds.Tables[3].Columns.Count;

        //테이블 존재여부 검사
        if (oDoc.Tables.Count != 0)
        {
            //테이블 생성하기
            //테이블 Header 셋팅
            tb3 = oDoc.Tables.Add(wrdRng7, 1, tb3ColCnt, ref oMissing, ref oMissing);
            tb3.Range.Tables[1].Rows[1].Cells[1].Range.Text = "Title1";
            tb3.Range.Tables[1].Rows[1].Cells[2].Range.Text = "Title2";
            tb3.Range.Tables[1].Rows[1].Cells[3].Range.Text = "Title3";
            tb3.Range.Tables[1].Rows[1].Cells[4].Range.Text = "Title4";
            tb3.Range.Tables[1].Rows[1].Cells[5].Range.Text = "Title5";
            tb3.Range.Tables[1].Rows[1].Cells[6].Range.Text = "Title6";
            tb3.Range.Tables[1].Rows[1].Cells[7].Range.Text = "Title7";

            //테이블 Cell 넓이, 스타일
            tb3.Range.Tables[1].Rows[1].Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[2].SetWidth(70, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[3].SetWidth(150, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[4].SetWidth(25, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[5].SetWidth(100, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[6].SetWidth(40, Word.WdRulerStyle.wdAdjustNone);
            tb3.Range.Tables[1].Rows[1].Cells[7].SetWidth(40, Word.WdRulerStyle.wdAdjustNone);
        }

        //데이터로우로 부터 테이블에 데이터를 추가한다.
        if (tb3.Range.Tables.Count > 0)
        {
            try
            {
                Microsoft.Office.Interop.Word.Row newRow = null;
                if (tb3RowCnt == 0)
                {
                    //newRow.Cells.Merge();
                }
                else
                {
                    for (int i = 0; i < tb3RowCnt; i++)
                    {
                        newRow = tb3.Range.Tables[1].Rows.Add(ref oMissing);
                        newRow.Cells[1].SetWidth(130, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[2].SetWidth(70, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[3].SetWidth(150, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[4].SetWidth(25, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[5].SetWidth(100, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[6].SetWidth(40, Word.WdRulerStyle.wdAdjustNone);
                        newRow.Cells[7].SetWidth(40, Word.WdRulerStyle.wdAdjustNone);

                        //루프를 돌면서 Cell에 내용을 출력
                        for (int j = 0; j < tb3ColCnt; j++)
                        {
                            int k = j + 1;
                            newRow.Cells[k].Range.Text = ds.Tables[3].Rows[i][j].ToString();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
           
            }
        }

        //테이블 보더 스타일
        tb3.Borders.InsideLineStyle     = Word.WdLineStyle.wdLineStyleSingle;
        tb3.Borders.OutsideLineStyle    = Word.WdLineStyle.wdLineStyleSingle;

        return tb3;
    }
    #endregion

    #endregion

    #region Draw Graph Method
    ///// <summary>
    /////  Draw Graph Method
    ///// </summary>
    //private void DrawGraph()
    //{
    //    //오늘 날짜
    //    string strMonth = DateTime.Now.Month.ToString();
    //    string strDay = DateTime.Now.Day.ToString();

    //    if (int.Parse(strMonth) < 10)
    //        strMonth = "0" + strMonth;

    //    if (int.Parse(strDay) < 10)
    //        strDay = "0" + strDay;

    //    string nowDate = DateTime.Now.Year.ToString() + strMonth + strDay;
    //    string spName = "dbo.XXXXX";

    //    SqlParameter[] param = new SqlParameter[3];
    //    param[0] = new SqlParameter("@CompCode", CustId);
    //    param[1] = new SqlParameter("@FDate", nowDate);
    //    param[2] = new SqlParameter("@TDate", this.cal_Month.Value.Substring(0, 4) + this.cal_Month.Value.Substring(5, 2) + "31");

    //    SqlHelper dac = new SqlHelper();
    //    DataSet ds = dac.ExecuteDataset(ConnectionString, CommandType.StoredProcedure, spName, param);

    //    //Chart 설정
    //    Graph.Chart wrdChart;
    //    Graph.Axis axis;
    //    DataTable dtSheet = ds.Tables[0];
    //    object oClassType = "MSGraph.Chart.8";

    //    //차트
    //    wrdChart = (Graph.Chart)wrdRng7.InlineShapes.AddOLEObject(ref oClassType, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing).OLEFormat.Object;

    //    wrdChart.Application.PlotBy = Graph.XlRowCol.xlColumns;
    //    wrdChart.ChartType = Microsoft.Office.Interop.Graph.XlChartType.xlAreaStacked;
    //    axis = (Graph.Axis)wrdChart.Axes(1, 1);

    //    //Make Header of Sheet
    //    wrdChart.Application.DataSheet.Cells.Clear();
    //    for (int i = 0; i < dtSheet.Columns.Count; i++)
    //    {
    //        wrdChart.Application.DataSheet.Cells[1, i + 1] = dtSheet.Columns[i].ColumnName;
    //    }

    //    //Make DataSheet
    //    for (int i = 0; i < dtSheet.Rows.Count; i++)
    //    {
    //        for (int j = 0; j < dtSheet.Columns.Count; j++)
    //        {
    //            wrdChart.Application.DataSheet.Cells[i + 2, j + 1] = dtSheet.Rows[i][j].ToString();
    //        }
    //    }

    //    wrdChart.Width = 500;
    //    //지연시간이 필요할 경우
    //    //Thread.Sleep(3000);
    //    wrdChart.Application.Quit();
    //}
    #endregion

    #endregion

    #region UI 부분(MakeSubMenu, btnResult_Click, makeDate)

    #region 서브메뉴생성 메서드
    /// <summary>
    /// 서브 매뉴 생성
    /// </summary>
    private void MakeSubMenu()
    {
        HtmlGenericControl id1 = (HtmlGenericControl)Page.FindControl("divMenu1");
        HtmlGenericControl id2 = (HtmlGenericControl)Page.FindControl("divMenu2");
        HtmlGenericControl id3 = (HtmlGenericControl)Page.FindControl("divMenu3");
        HtmlGenericControl id4 = (HtmlGenericControl)Page.FindControl("divMenu4");
        HtmlGenericControl id5 = (HtmlGenericControl)Page.FindControl("divMenu5");

        AuthMenu(CustGrade, id1, id2, id3, id4, id5);
        string loginYN = "";

        this.t_Title_Sub.InnerHtml = "";
    }
    #endregion

    #region 조회 버튼클릭 이벤트 메서드
    /// <summary>
    /// 조회 버튼클릭 이벤트 메서드
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnResult_Click(object sender, EventArgs e)
    {
        //기준월
        nowDate = this.cal_Month.Value.Substring(0, 4) + this.cal_Month.Value.Substring(5, 2);

        //Assingment Bookmark name
        AssignBookmarkName();

        CreateDoc();

        //Download path
        ShowWordMht1.FilePath = mhtFileName.ToString();
        //ShowWordMht1.FilePath = mhtFileName.ToString();
           
        UpdateProgress1.AssociatedUpdatePanelID = this.upPnlShowWord.UniqueID;
        Thread.Sleep(1000);
    }
    #endregion

    #region 북마크할당 메서드
    /// <summary>
    /// 북마크할당 메서드
    /// </summary>
    private void AssignBookmarkName()
    {
            //북마크 아이디 할당
            bookmark1 = "bm1";
            bookmark2 = "bm2";
            bookmark3 = "bm3";
            bookmark4 = "bm4";
            bookmark5 = "bm5";
            bookmark6 = "bm6";
            bookmark7 = "bm7";
    }
    #endregion

    #endregion
}

'General .NET' 카테고리의 다른 글

HttpWebRequest  (0) 2007/12/17
HttpWebRequest  (0) 2007/12/17
VSTO - Word Automation  (0) 2007/12/17
Socket Class  (0) 2007/12/17
DataTable.NewRow  (0) 2007/12/17
int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:26

Socket Class General .NET2007/12/17 10:26

필요한 네임스페이스

System.Net, System.Net.Sockets

 

System.Net.Sockets.Socket 클래스의 특징

- 클라이언트 응용프로그램과 서버 응용 프로그램에서도 소켓으로 사용 가능

- 동기, 비동기 동작을 모두 사용가능

 

endpoint

- 네트워크 케이블의 양 끝(종단점)

- 네트워크에 대한 읽기, 쓰기를 수행

 

클라이언트와 서버 응용 프로그램은 소켓 연결을 통해서 통신하고 바이트 스트림을 주고 받는다. 다른 소켓으로 메시지를 보내기 위해서는 응용 플로그램을 제공하는 PC의 아이피 주소와 소프트웨어의 프로세스 식별자를 알아야 한다.

PC에서 소프트웨어 프로세스 식별자는 포트라고 하는 고유한 숫자를 사용.

따라서 응용 프로그램에서 연결의 반대편 끝에 있는 다른 소켓에 메시지를 전달하려면 상대편 IP주소와 응용 프로그램의 포트 번호를 알아야 한다.

 

닷넷 프레임워크에서는 소켓의 기능을 System.Net.Sockets.Socket 클래스로 제공.

인터넷을 사용하는 소켓 응용 프로그램을 작성하므로 AddressFamily.InterNetwork를 사용한다.

 

[소캣구성]

소켓 객체를 생성하고 사용하기 위한 Socket 클래스의 생성자

public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)

 

소켓 객체의 생성자는 3가지 열거형 AddressFamily, SocketType, ProtocolType을 인자로 받으며 각 열거형은 System.Net.Sockets 네임스페이스에 정의되어 있다.

 

AddressFamily 열거형

- Socket 객체가 주소를 풀이하기 위해 사용하는 주소 지정 스키마를 정의.

- 여기서는 인터넷을 사용하므로 AddressFamily.InterNetWork를 사용.

 

SocketType 열거형

- 소켓의 종류를 지정, 가장 많이 사용되는 소켓의 종류는 SocketType.Stream

- Stream은 양방향 연결 기반 바이트 스트림을 제공.

 

ProtocolType 열거형

- 소켓이 통신을 하기 위해 사용하는 저수준 프로토콜의 종류를 지정.

- TCP, AddresssFamily.InterNetwork를 사용해야 함.

 

) 소켓객체의 인스턴스를 생성

Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

 

[원격서버에 연결하기]

Socket클래스의 Connect()를 사용하여 원격서버에 연결.(동기적 시도)

Connect() 메소드의 서명

- public void Connect( EndPoint remoteEP);

 

Connect() 메소드 인자

- System.Net.EndPoint 클래스의 인스턴스

- EndPoint 클래스는 추상 클래스로 네트워크 주소를 의미한다

- EndPoint 클래스의 하위 클래스는 System.Net.IPEndPoint

- Connect() 메소드를 사용할 때는 연결하려는 원격 서버의 IP 주소와 포트 번호를 포함한 IPEndPoint 객체를 인자로 사용해야 함.

 

IPEndPoint객체의 2가지 생성자

public IPEndPoint(long address, int port);

public IPEndPoint(IPAddress address, int port); (가장 자주 사용함)

'General .NET' 카테고리의 다른 글

HttpWebRequest  (0) 2007/12/17
VSTO - Word Automation  (0) 2007/12/17
Socket Class  (0) 2007/12/17
DataTable.NewRow  (0) 2007/12/17
int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
닷넷 전용 어셈블리  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:26

DataTable.NewRow General .NET2007/12/17 10:26

private void MakeDataTableAndDisplay()
{
    // Create new DataTable and DataSource objects.
    DataTable table = new DataTable();

    // Declare DataColumn and DataRow variables.
    DataColumn column;
    DataRow row; 
    DataView view;

    // Create new DataColumn, set DataType, ColumnName and add to DataTable.    
    column = new DataColumn();
    column.DataType = System.Type.GetType("System.Int32");
    column.ColumnName = "id";
    table.Columns.Add(column);
 
    // Create second column.
    column = new DataColumn();
    column.DataType = Type.GetType("System.String");
    column.ColumnName = "item";
    table.Columns.Add(column);
 
    // Create new DataRow objects and add to DataTable.    
    for(int i = 0; i < 10; i++)
    {
        row = table.NewRow();
        row["id"] = i;
        row["item"] = "item " + i.ToString();
        table.Rows.Add(row);
    }
 
    // Create a DataView using the DataTable.
    view = new DataView(table);

    // Set a DataGrid control's DataSource to the DataView.
    dataGrid1.DataSource = view;
}

'General .NET' 카테고리의 다른 글

VSTO - Word Automation  (0) 2007/12/17
Socket Class  (0) 2007/12/17
DataTable.NewRow  (0) 2007/12/17
int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
닷넷 전용 어셈블리  (0) 2007/12/17
델리게이트  (0) 2007/12/17
Posted by -세티-
public static int Parse(string s)
{

return int.Parse(s, NumberStyles.Integer, null);

}

public static int Parse(string s, NumberStyles style, IFormatProvider provider)
{

NumberFormatInfo info1 = NumberFormatInfo.GetInstance(provider);

NumberFormatInfo.ValidateParseStyle(style);

return Number.ParseInt32(s, style, info1);

}


public static int ToInt32(string value)
{
          if (value == null)
                    return 0;
          return int.Parse(value);

}

'General .NET' 카테고리의 다른 글

Socket Class  (0) 2007/12/17
DataTable.NewRow  (0) 2007/12/17
int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
닷넷 전용 어셈블리  (0) 2007/12/17
델리게이트  (0) 2007/12/17
제너릭  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:25

닷넷 전용 어셈블리 General .NET2007/12/17 10:25

어셈블리 전용(Private) 또는 공유(Shared) 형태로 배포됨.

l         전용과 공유의 차이점 명명 규칙과 버전관리 정책

 

l         전용 어셈블리의 특징

n         배포된 응용 프로그램에 의해서만 이용될 수 있는 모듈들의 집합.

n         해당 형식들을 소유하는응용 프로그램만이 이 형식들을 사용할 수 있고 시스템의 다른 응용 프로그램과 공유하지 않게 한다는 것을 의미.

n         클라이언트 응용 프로그램과 동일한 디렉토리(응용 프로그램 디렉토리)나 그 하위 디렉토리에 있어야 함.

n         전용 어셈블리의 resolution과 로딩은 어셈블리가 위치한 응용 프로그램 디렉토리(bin 디렉토리)에서 일어난다. 옮겨도 실행됨.

n         삭제를 하여도 머신의 다른 응용 프로그램에는 손상을 주지 않음.

 

l         전용 어셈블리 프로빙(기초)

n         프로빙 외부 어셈블리 참조자를 정확히 상응하는 바이너리 파일에 매핑하는 과정

n         프로빙이란?

u        닷넷 런타임이 어떤 모듈의 매니페스트로부터 .assembly extern CarLibrary 라는 라인을 읽게 되면 CarLibrary.dll이라는 이름의 파일을 검색한다. 이 때 이 파일을 검색할 수 없게 된다면 *.exe 버전을 검색하게 된다. 이 두 파일이 모두 검색되지 않으면 런타임 예외를 발생시킨다. 그러나 XML 구성 파일(*.config)을 이용하게 되면 런타임이 응용 프로그램 디렉토리 밖의 다른 위치에 에서 프로브하게 할 수 있다.

 

l         전용 어셈블리 식별하기

n         전용 어셈블리 식별자 문자열 이름과 숫자 버전으로 구성.

n         문자열 이름 어셈블리의 매니페스트를 포함하는 바이너리 모듈의 이름에 기초해서 만들어진다.

Ex) CarLibrary.dll 어셈블리의 매니페스트

.assembly CarLibrary

{

….

.ver 1:0:454:30104 ß--- 버전 번호는 다를 수 있다.

}

어셈블리의 버전 정책은 닷넷 런타임이 어셈블리를 로딩할 때 적용하려 하지 않을 것이다. 그 이유는 이 전용 어셈블리를 알고 있는 것은 바로 해당 클라이언트 응용 프로그램밖에 없기 때문이다. 그렇기 때문에 전용 어셈블리에 대해서는 정확한 버전 검사를 할 필요가 없는 것이다.

 

 

Reference

1. Part3 .NET 어셈블리를 이용한 프로그래밍, 9장 .NET 어셈블리, C# and the .NET Platform, p.440~442

'General .NET' 카테고리의 다른 글

DataTable.NewRow  (0) 2007/12/17
int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
닷넷 전용 어셈블리  (0) 2007/12/17
델리게이트  (0) 2007/12/17
제너릭  (0) 2007/12/17
C# '전처리기' 지시문  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:24

델리게이트 General .NET2007/12/17 10:24

1. 닷넷 델리게이트

-         응용 프로그램 내에 있는 다른 메소드를 가리키는 객체

1.1 델리게이트가 포함하는 3가지 중요한 정보

-         델리게이트가 호출하는 메소드 이름

-         이 메소드의 인수

-         이 메소드의 반환값

1. 2 닷넷 프레임워크에서는 동기 델리게이트와 비동기 델리게이트를 이용하는 것이 가능.

 

2. C#에서 델리게이트 정의하기

-         delegate 키워드를 사용.

-         내부적으로 System.MulticastDelegate로부터 파생되는 봉인 클래스가 생성됨.

Ex) public delegate void PlayAcidHouse(Person theDJ, int volumn);

sealed class PlayAcidHouse : System.MulticastDelegate

{

         public PlayAcidHouse(object target, unit functionAddress)

         public void Invoke(Person theDJ, int volumn)
         public IAsyncResult BeginInvoke(Person theDJ, int volumn, AsynCallback cb, object state)
         public void EndInvoke(IAsyncResult result)

}

 

-         PalyAcidHouse 클래스에는 자동적으로 3개의 public 메소드가 만들어짐.

-         Invoke() : 델리게이트에게 현재 지시하고 있는 메소드를 호출할 때를 알리기 위해서 호출, C#에서 직접 호출 불가능

-         BeginInvoke(), EndInvoke() 는 비동기 호출하는데 이용

'General .NET' 카테고리의 다른 글

int.Parse(int value)와 Convert.ToInt(object value)와의 차이점  (0) 2007/12/17
닷넷 전용 어셈블리  (0) 2007/12/17
델리게이트  (0) 2007/12/17
제너릭  (0) 2007/12/17
C# '전처리기' 지시문  (0) 2007/12/17
XML in the .NET Framework  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:23

제너릭 General .NET2007/12/17 10:23

MSDN - Generic 소개


1. 제너릭 클래스와 메서드가 있다.

2. 제너릭 형식에서만 가능.

3. 재사용성, 형식 안정성, 효율성 달성이 가능.

4. 컬렉션과 컬렉션을 다루는 메서드에서 일반적으로 사용.

5. System.Collections.Generic 네임스페이스에 제너릭 기반 컬렉션 클래스가 존재.



using System;
using System.Collections.Generic;
using System.Text;

namespace VS2005
{
 //T형식 파라미터
 public class GenericClassTest<T>
 {
  //중첩된 Node 클래스도 T 제너릭
  public class Node
  {
   //T as private member data type
   private T data;
   public T Data
   {
    get { return data; }
    set { data = value; }
   }

   private Node head;
   public Node next;
   public Node Next
   {
    get { return next; }
    set { next = value; }
   }

   //중첩 Node 클래스의 생성자
   //생성자가 T를 받아서 타입을 결정
   public Node(T t)
   {
    next = null;
    Data = t;
   }
  }

  public GenericClassTest()
  {
   head = null;
  }

  public void AddHead(T t)
  {
   Node n = new Node(t);
   n.next = head;
   head = n;
  }
  public IEnumerator<T> GetEnumerator()
  {
   Node current = head;
   while(current != null)
   {
    yield return current.Data;
    current = current.Next;
   }
  }
 
 }

 public class GenericTest
 {
  public static void Main()
  {
   GenericClassTest<int> list = new GenericClassTest<int>();
   for (int i = 0; i < 10; i++ )
   {
    list.AddHead(i);
   }

   foreach (int i in list)
   {
    System.Console.Write(i + "");
   }
   System.Console.WriteLine("\nDone");
  }
 }
}

'General .NET' 카테고리의 다른 글

닷넷 전용 어셈블리  (0) 2007/12/17
델리게이트  (0) 2007/12/17
제너릭  (0) 2007/12/17
C# '전처리기' 지시문  (0) 2007/12/17
XML in the .NET Framework  (0) 2007/12/17
XML Data  (0) 2007/12/17
TAG
Posted by -세티-
2007/12/17 10:23

C# '전처리기' 지시문 General .NET2007/12/17 10:23

최초 작성자 세티
최초 작성일 2006년 8월 13일 일요일
최종 수정일
최종 수정자
C# '전처리기' 지시문

정의 : 컴파일 과정을 제어하기 위해서 사용됨.

C# 전처리기 지시문
#define, #undef - 조건부 컴파일 기호를 정의하거나 정의를 해제 하는데 이용.
#if, #elif, #else, #endif - 소스 코드의 일부를 조건적으로 건터뛰는데 이용.
#line - 에러와 경고의 줄 번호를 제어하는데 이용.
#error, #warning - 해당 빌드에 대한 에러와 경고 생성하는 데 이용.
#region, #endregion - 소스 코드의 일부를 명시적으로 표시하는데 이용.
- 표시된 영역 안의 코드는 확장, 축소 될 수 있다.


#region, #endregion 를 이용하여 코드 영역 지정하기
#region 전처리기를 이용한 코드 영역 지정하기
public class Class1
{
   //내용
}
public interface Interface1
{
   //내용
}
#endregion

조건부 코드 컴파일하기
- #if, #elseif, #else, #endif 를 사용하여 코드 블록을 조건적으로 컴파일 하게 한다.
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            #if(DEBUG)
            #warning 경고! Debug가 정의되어 있음. 릴리즈 빌드로 구성하시오.
            Console.WriteLine("App directory:{0}", Environment.CurrentDirectory);
            Console.WriteLine("Box: {0}", Environment.MachineName);
            Console.WriteLine("OS: {0}", Environment.OSVersion);
            Console.WriteLine(".NET Version: {0}", Environment.Version); Console.ReadLine(); #endif
        }
    }
}

'General .NET' 카테고리의 다른 글

델리게이트  (0) 2007/12/17
제너릭  (0) 2007/12/17
C# '전처리기' 지시문  (0) 2007/12/17
XML in the .NET Framework  (0) 2007/12/17
XML Data  (0) 2007/12/17
XML Readers and Writers  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:22

XML in the .NET Framework General .NET2007/12/17 10:22

작성자 : 박종현
작성일: 2007-09-05
원문 :
http://samples.gotdotnet.com/quickstart ··· xml.aspx

* 번역에 오역이 있을 수 있습니다.

XML in the .NET Framework

Extensible Markup Language (XML) 는 구조화된 데이터를 기술하기 위한 하나의 포맷을 제공하는 메타-마크업 언어이다. XML은 웹 기반의 데이터를 보여주고, 교정을 가능하게 하는 새로운 세대의 어플리케이션을 가능하게 해준다. XML은 웹 상의 데이터를 위한 공용 언어이다. XML은 어플리케이션들의 광대하고 다양한 구조화된 데이터들을 로컬 컴퓨테이션과 프리젠테이션을 위한 데스크탑으로 강력한 배포의 기회를 개발자들에게 제공한다.


System.Xml Namespace

아래는 System.Xml Namespace에서 XML 클래스들의 어법을 다룬다.

이 네임스페이스들은 파싱, 벨리데이션 그리고 XML 데이터의 교정을 위한 리더들, 라이터들의 포괄적인 집합과 World Wide Web Consortium (W3C) DOM-compliant 컴폰넌트들을 가진다.
그것은 또한 XML Path Language (XPath) 쿼리들과 and Extensible Stylesheet Language Transformations (XSLT)를 포함한다. 다음은 XML 네임스페이스내의 많은 클래스들을 포함하는 리스트 이다.

XmlTextReader 클래스는 XML 데이터를 단지 빠르게 읽고, 캐쉬되지 않는다.
XmlNodeReader 클래스는 DOM 노드의 서브트리 상단에 위치하는 XmlReader를 제공한다.
XmlValidatingReader 클래스는 DTD, XDR 그리고 XSD 스키마의 합당성 여부를 판단한다.
XmlTextWriter 클래스는 순차적으로 빠르게 XML을 추가하는데 사용한다.
XmlDocument 클래스는 W3C Document Object Model level 1 Core 와 the Core DOM Level 2를 실행한다.
XmlDataDocument 클래스는 DataSet을 지원할 수 있는 XML Document 도구를 제공한다. 구조화된 XML은 XML Document의 트리 표현이나 DataSet의 관계 표현을 통해서 보여질 수 있고 동시에 교정될 수 있다.
XPathDocument 클래스는 XSLT를 위한 XML 문서 프로세싱을 위한 빠르고 퍼포먼트한 캐쉬를 제공한다.

XPathNavigator 클래스는 네비게이션을 위한 하나의 커서 스타일 모델로써 저장보다는 W3C XPath 1.0 data 모델을 제공한다.
XslTransform 클래스는 XML문서들을 변형하기 위한 XSLT 프로세서로 W3C XSLT 1.0 이라는 특정한 컴파일러를 제공한다.
XmlSchema 객체 모델 클래스들은 W3C XSD 규약의 직접적으로 영향을 미치는 클래스들의 집합을 찾아가도록 도와주는 기능을 제공한다.
XmlSchemaCollection 클래스는 XDR 와 XSD 스키마들의 라이브러리들을 제공한다. 이 스키마들, 메모리에 캐쉬된 XmlValidatingReader를 위해 파서-타임 유효성 검증을 빠르게 도와준다.

'General .NET' 카테고리의 다른 글

제너릭  (0) 2007/12/17
C# '전처리기' 지시문  (0) 2007/12/17
XML in the .NET Framework  (0) 2007/12/17
XML Data  (0) 2007/12/17
XML Readers and Writers  (0) 2007/12/17
C#으로 XML문서 생성하기  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:22

XML Data General .NET2007/12/17 10:22

작성자 : 박종현
작성일 : 2007-09-05
출처 :
http://samples.gotdotnet.com/quickstart ··· ile.aspx


XML Data

Overview of XML

 

XML in the .NET Framework

 

Extensible Markup Language (XML) 는 구조화된 데이터를 기술하기 위한 하나의 포맷을 제공하는 메타-마크업 언어이다. XML은 웹 기반의 데이터를 보여주고, 교정을 가능하게 하는 새로운 세대의 어플리케이션을 가능하게 해준다. XML은 웹 상의 데이터를 위한 공용 언어이다. XML은 어플리케이션들의 광대하고 다양한 구조화된 데이터들을 로컬 컴퓨테이션과 프리젠테이션을 위한 데스크탑으로 강력한 배포의 기회를 개발자들에게 제공한다.

 


System.Xml Namespace

 

아래는 System.Xml Namespace에서 XML 클래스들의 어법을 다룬다.

 

이 네임스페이스들은 파싱, 벨리데이션 그리고 XML 데이터의 교정을 위한 리더들, 라이터들의 포괄적인 집합과 World Wide Web Consortium (W3C) DOM-compliant 컴폰넌트들을 가진다.

그것은 또한 XML Path Language (XPath) 쿼리들과 and Extensible Stylesheet Language Transformations (XSLT)를 포함한다. 다음은 XML 네임스페이스내의 많은 클래스들을 포함하는 리스트 이다.

 


XmlTextReader
클래스는 XML 데이터를 단지 빠르게 읽고, 캐쉬되지 않는다.

XmlNodeReader 클래스는 DOM 노드의 서브트리 상단에 위치하는 XmlReader를 제공한다.

XmlValidatingReader 클래스는 DTD, XDR 그리고 XSD 스키마의 합당성 여부를 판단한다.

XmlTextWriter 클래스는 순차적으로 빠르게 XML을 추가하는데 사용한다.

XmlDocument 클래스는 W3C Document Object Model level 1 Core the Core DOM Level 2를 실행한다.

XmlDataDocument 클래스는 DataSet을 지원할 수 있는 XML Document 도구를 제공한다. 구조화된 XML XML Document의 트리 표현이나 DataSet의 관계 표현을 통해서 보여질 수 있고 동시에 교정될 수 있다.

XPathDocument 클래스는 XSLT를 위한 XML 문서 프로세싱을 위한 빠르고 퍼포먼트한 캐쉬를 제공한다.

XPathNavigator 클래스는 네비게이션을 위한 하나의 커서 스타일 모델로써 저장보다는 W3C XPath 1.0 data 모델을 제공한다.

XslTransform 클래스는 XML문서들을 변형하기 위한 XSLT 프로세서로 W3C XSLT 1.0 이라는 특정한 컴파일러를 제공한다.

XmlSchema 객체 모델 클래스들은 W3C XSD 규약의 직접적으로 영향을 미치는 클래스들의 집합을 찾아가도록 도와주는 기능을 제공한다.

XmlSchemaCollection 클래스는 XDR XSD 스키마들의 라이브러리들을 제공한다. 이 스키마들, 메모리에 캐쉬된 XmlValidatingReader를 위해 파서-타임 유효성 검증을 빠르게 도와준다.

'General .NET' 카테고리의 다른 글

C# '전처리기' 지시문  (0) 2007/12/17
XML in the .NET Framework  (0) 2007/12/17
XML Data  (0) 2007/12/17
XML Readers and Writers  (0) 2007/12/17
C#으로 XML문서 생성하기  (0) 2007/12/17
String.Format 메서드  (0) 2007/12/17
TAG XML Data
Posted by -세티-
2007/12/17 10:21

XML Readers and Writers General .NET2007/12/17 10:21

작성자: 박종현
작성일: 2007-09-05
출처:
http://samples.gotdotnet.com/quickstart ··· ile.aspx



XML Readers and Writers

Read XML from a file

 



파일에서 XML을 읽는 방법

XmlReader 클래스는 XML 파싱을 제공하는 API 이다.

XmlTextReader는 바이트 스트림들을 핸들하기 위해 디자인된 도구이다.

 

일반적으로, 당신이 DOM Overhead가 없는 가공되지 않은 Xml 데이터를 읽기를 원한다면 XmlTextReader를 사용한다.

 

아래는 books.xml 이다.

<?xml version="1.0" ?>

<bookstore>

             <book genre="autobiography" publicationdate="1981" ISBN="1-861003-11-0">

                           <title>The Autobiography of Benjamin Franklin</title>

                           <author>

                                        <first-name>Benjamin</first-name>

                                        <last-name>Franklin</last-name>

                           </author>

                           <price>8.99</price>

             </book>

             <book genre="novel" publicationdate="1967" ISBN="0-201-63361-2">

                           <title>The Confidence Man</title>

                           <author>

                                        <first-name>Herman</first-name>

                                        <last-name>Melville</last-name>

                           </author><price>11.99</price>

             </book>

             <book genre="philosophy" publicationdate="1991" ISBN="1-861001-57-6">

                           <title>The Gorgias</title>

                           <author>

                                        <name>Plato</name>

                           </author>

                           <price>9.99</price>

             </book>

</bookstore>

 

다음은 이것을 읽어들이는 C#코드이다.

XML파일을 읽기 위해 2가지의 네임스페이스를 추가한다.

using System.Xml;

using System.Text;

 

아래의 코드에서는 XML의 부모 노드 정보만 가져온다.

//읽어올 XML 파일을 XmlTextReader 객체에 담는다.

XmlTextReader reader = new XmlTextReader(

@"D:\wwwroot\Pilot_Web\AboutOnlyXML\books1.xml"

);

 

//출력을 위한 StringBuilder를 인스턴스화 한다.

StringBuilder sb = new StringBuilder();

 

//파일을 읽는다.

while(reader.Read())

{

//노드가 발견되면 엘리먼트를 읽고, 엘리먼트에 어트리뷰트도 읽어들인다.

switch (reader.NodeType)

{

case XmlNodeType.Element: //노드는 엘리먼트이다.

sb.Append("<"+ reader.Name);

while (reader.MoveToNextAttribute()); //Read Attribute

{

   sb.Append(" " + reader.Name + "='" + reader.Value + "'");

}

                  sb.Append(">");

                           break;

case XmlNodeType.DocumentType:             //노드의 문서타입

sb.Append(reader.NodeType + "<" + reader.Name + ">" + reader.Value);

break;

}

this.lblReadXMLData.Text = sb.ToString();

}

 

이것의 출력 결과는 아래와 같다.

<bookstore>

<book genre='autobiography' publicationdate='1981' ISBN='1-861003-11-0'>

<title>

<author>

<first-name>

<last-name>

<price>

<book genre='novel' publicationdate='1967' ISBN='0-201-63361-2'>

<title>

<author>

<first-name>

<last-name>

<price>

<book genre='philosophy' publicationdate='1991' ISBN='1-861001-57-6'>

<title>

<author>

<name>

<price>

 

XmlNodeType XmlReader 클래스에 의해 의존적이고 리턴된다.

XmlTextReader 클래스는 XmlNodeType Document, Documentfragment, Entity, EndEntity 그리고 Notation 노드를 리턴한다.

 

 

 

 

XmlNodeType Enumeration Member

Description

Attribute

어트리뷰트.
XML: id='123'.
어트리뷰트는 자식 노드 타입을 가질 수 있다.: 텍스트와 엔티티 참조.  Attribute 노드는 다른 노드타입의 자식노드로 나타날 수 없다.

CDATA

CDATA 섹션.
: <![CDATA[my escaped text]]>
CDATA
섹션은 자식 노드들을 가질 수 없다. CDATA섹션 노드는 DocumentFragment, EntityReference, and Element nodes의 자식노드에 나타날 수 있다.

Comment

코멘트

: <!-- my comment -->

코멘트 노드는 자식 노드를 가질 수 없다. Document, DocumentFragment, Element, and EntityReference nodes의 자식노드에 나타날 수 있다.

Document

문서객체는 xml 문서 전체의 액세스 제공자, 문서 트리의 루트.

Document 노드는 다음의 자식노드 타입을 가진다.: Element (maximum of one), ProcessingInstruction, Comment, and DocumentType. The Document node cannot appear as the child of any node types.

DocumentFragment

document fragment.
DocumentFragment
노드는 서브트리나 노드의 악세서리다.

DocumentFragment 노드는 다음의 자식노드 타입을 가질 수 있다. :

Element, ProcessingInstruction, Comment, Text, CDATASection, and EntityReference.

DocumentFragment node는 자식노드타입에 나타날 수 없다.

DocumentType

Document  타입 선은 <!DOCTYPE> 태그를 사용.

XML: <!DOCTYPE ...>
DocumentType
노드는 다음의 자식 노드를 가진다.: Notation and Entity.

DocumentType 노드는 문서타입의 자식노드로 나타날 수 있다.

Element

엘리먼트
XML: <Name>
Element
노드는 다음의 자식노드 타입을 가질 수 있다.:

Element, Text, Comment, ProcessingInstruction, CDATA,

그리고 EntityReference.

Element 노드는 Document, DocumentFragment, EntityReference, Element nodes들의 자식노드에 나타날 수 있다.

EndElement

XmlReaderelement의 끝에 다다를 때 리턴되는 값

XML: </foo>

EndEntity

Returned when XmlReader gets to the end of the entity replacement as a result of a call to ResolveEntity.

Entity

엔티티 선언
XML: <!ENTITY ...>
Entity node can have child nodes that represent the expanded entity (for example, Text and EntityReference nodes). The Entity node can appear as the child of the DocumentType node.

EntityReference

엔티티참조
XML: &foo;
This applies to all entities, including character entity references. An EntityReference node can have the following child node types: Element, ProcessingInstruction, Comment, Text, CDATASection, and EntityReference. The EntityReference node can appear as the child of the Attribute, DocumentFragment, Element, and EntityReference nodes.

None

This is returned by the XmlReader if a Read method has not been called.

Notation

A notation in the document type declaration.
XML: <!NOTATION ...>
A Notation node cannot have any child nodes. The Notation node can appear as the child of the DocumentType node.

ProcessingInstruction

A processing instruction (PI).
XML: <?pi test?>
A PI node cannot have any child nodes. The PI node can appear as the child of the Document, DocumentFragment, Element, and EntityReference nodes.

SignificantWhitespace

Whitespace between markup in a mixed content model, or whitespace within the xml:space= "preserve" scope.

Text

The text content of an element. A Text node cannot have any child nodes. The Text node can appear as the child node of the Attribute, DocumentFragment, Element, and EntityReference nodes.

Whitespace

Whitespace between markup.

XmlDeclaration

The XML declaration node.
Example XML: <?xml version='1.0'?>
This has to be the first node in the document. It can have no children. It is a child of the root node. It can have attributes that provide version and encoding information.

 

그럼 이제 books.xml 이 가지는 모든 엘리먼트와 어트리뷰트를 읽어보도록 하겠습니다.

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.IO;

using System.Xml;

using System.Text;

 

public partial class AboutOnlyXML_ReadXMLFile : System.Web.UI.Page

{

             private const string document = @"D:\wwwroot\Pilot_Web\AboutOnlyXML\books.xml";

 

             public static void Main()

             {

                           AboutOnlyXML_ReadXMLFile myReadXmlFileSample = new AboutOnlyXML_ReadXMLFile();

                           myReadXmlFileSample.Run(document);

             }

 

             public void Run(String args)

             {

                           XmlTextReader reader = null;

 

                           try

                           {

                                        Console.WriteLine("읽을 파일 {0} ...", args);

                                       

                                        reader = new XmlTextReader(args);

                                        Console.WriteLine("파일 {0} 을 성공적으로 읽었습니다....", args);

 

                                        Console.WriteLine("출력을 시작합니다.");

                                        Console.WriteLine();

                                        FormatXml(reader, args);

                           }

                           catch (Exception e)

                           {

                                        Console.WriteLine("Failed to read the file {0}", args);

                                        Console.WriteLine("Exception: {0}", e.ToString());

                           }

 

                           finally

                           {

                                        Console.WriteLine();

                                        Console.WriteLine("Processing of the file {0} complete.", args);

                                        // Finished with XmlTextReader

                                        if (reader != null)

                                                     reader.Close();

                           }

             }

 

             private static void FormatXml(XmlReader reader, String filename)

             {

                           int declarationCount = 0, piCount = 0, docCount = 0, commentCount = 0, elementCount = 0, attributeCount = 0, textCount = 0, whitespaceCount = 0;

 

                           while (reader.Read())

                           {

                                        switch (reader.NodeType)

                                        {

                                                     case XmlNodeType.XmlDeclaration:

                                                                  Format(reader, "XmlDeclaration");

                                                                  declarationCount++;

                                                                  break;

                                                     case XmlNodeType.ProcessingInstruction:

                                                                  Format(reader, "ProcessingInstruction");

                                                                  piCount++;

                                                                  break;

                                                     case XmlNodeType.DocumentType:

                                                                  Format(reader, "DocumentType");

                                                                  docCount++;

                                                                  break;

                                                     case XmlNodeType.Comment:

                                                                  Format(reader, "Comment");

                                                                  commentCount++;

                                                                  break;

                                                     case XmlNodeType.Element:

                                                                  Format(reader, "Element");

                                                                  elementCount++;

                                                                  if (reader.HasAttributes)

                                                                                attributeCount += reader.AttributeCount;

                                                                  break;

                                                     case XmlNodeType.Text:

                                                                  Format(reader, "Text");

                                                                  textCount++;

                                                                  break;

                                                     case XmlNodeType.Whitespace:

                                                                  whitespaceCount++;

                                                                  break;

                                        }

                           }

 

                           // Display the Statistics for the file.

                           Console.WriteLine();

                           Console.WriteLine("Statistics for {0} file", filename);

                           Console.WriteLine();

                           Console.WriteLine("XmlDeclaration: {0}", declarationCount++);

                           Console.WriteLine("ProcessingInstruction: {0}", piCount++);

                           Console.WriteLine("DocumentType: {0}", docCount++);

                           Console.WriteLine("Comment: {0}", commentCount++);

                           Console.WriteLine("Element: {0}", elementCount++);

                           Console.WriteLine("Attribute: {0}", attributeCount++);

                           Console.WriteLine("Text: {0}", textCount++);

                           Console.WriteLine("Whitespace: {0}", whitespaceCount++);

             }

 

             private static void Format(XmlReader reader, String nodeType)

             {

                           Console.Write(reader.Depth + " ");

                           Console.Write(reader.AttributeCount + " ");

                           for (int i = 0; i < reader.Depth; i++)

                           {

                                        Console.Write('\t');

                           }

 

                           Console.Write(reader.Prefix + nodeType + "<" + reader.Name + ">" + reader.Value);

 

                           if (reader.HasAttributes)

                           {

                                        Console.Write(" Attributes:");

 

                                        for (int j = 0; j < reader.AttributeCount; j++)

                                        {

                                                     Console.Write(" [{0}] " + reader[j], j);

                                        }

                           }

                           Console.WriteLine();

             }

 

             protected void btnReadXML_Click(object sender, EventArgs e)

             {

                           StringWriter writer = new StringWriter();

                           Console.SetOut(writer);

                           AboutOnlyXML_ReadXMLFile myReadXmlFileSample = new AboutOnlyXML_ReadXMLFile();

                           myReadXmlFileSample.Run(Server.MapPath("books.xml"));

                           this.ouput.InnerHtml = writer.ToString();

 

             }

}

 

 

출력 결과

아래의 버튼을 클릭하면 XML 파일을 읽어옵니다.

 

파일에서 읽은 데이터를 출력합니다....

 

읽을 파일 D:\wwwroot\Pilot_Web\AboutOnlyXML\books.xml ...

파일 D:\wwwroot\Pilot_Web\AboutOnlyXML\books.xml 을 성공적으로 읽었습니다....

Processing ...

 

0 1 XmlDeclaration<xml>version="1.0" Attributes: [0] 1.0

0 0 Element<bookstore>

1 3        Element<book> Attributes: [0] autobiography [1] 1981 [2] 1-861003-11-0

2 0                      Element<title>

3 0                                   Text<>The Autobiography of Benjamin Franklin

2 0                      Element<author>

3 0                                   Element<first-name>

4 0                                                Text<>Benjamin

3 0                                   Element<last-name>

4 0                                                Text<>Franklin

2 0                      Element<price>

3 0                                   Text<>8.99

1 3        Element<book> Attributes: [0] novel [1] 1967 [2] 0-201-63361-2

2 0                      Element<title>

3 0                                   Text<>The Confidence Man

2 0                      Element<author>

3 0                                   Element<first-name>

4 0                                                Text<>Herman

3 0                                   Element<last-name>

4 0                                                Text<>Melville

2 0                      Element<price>

3 0                                   Text<>11.99

1 3        Element<book> Attributes: [0] philosophy [1] 1991 [2] 1-861001-57-6

2 0                      Element<title>

3 0                                   Text<>The Gorgias

2 0                      Element<author>

3 0                                   Element<name>

4 0                                                Text<>Plato

2 0                      Element<price>

3 0                                   Text<>9.99

 

Statistics for D:\wwwroot\Pilot_Web\AboutOnlyXML\books.xml file

 

XmlDeclaration: 1

ProcessingInstruction: 0

DocumentType: 0

Comment: 0

Element: 18

Attribute: 9

Text: 11

Whitespace: 25

 

Processing of the file D:\wwwroot\Pilot_Web\AboutOnlyXML\books.xml complete.

 

 

'General .NET' 카테고리의 다른 글

XML in the .NET Framework  (0) 2007/12/17
XML Data  (0) 2007/12/17
XML Readers and Writers  (0) 2007/12/17
C#으로 XML문서 생성하기  (0) 2007/12/17
String.Format 메서드  (0) 2007/12/17
Microsoft .NET Framework 3.0 Programming Model  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:20

C#으로 XML문서 생성하기 General .NET2007/12/17 10:20

using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Xml;

 

public partial class AboutOnlyXML_MakeXMLFile : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

                                   //xml문서 생성을 위해 xmlTextWriter인스턴스 객체를 생성한다.

                                   XmlTextWriter xmlTxtWriter = new XmlTextWriter(@"D:\wwwroot\Pilot_Web\AboutOnlyXML\NewBooks.xml", null);

 

                                   //XML 문서를 생성할 자식요소에 따라 들여쓰기를 한다.

                                   xmlTxtWriter.Formatting = Formatting.Indented;

 

                                   //XML선언을 작성한다.

                                   xmlTxtWriter.WriteStartDocument(false);

 

                                   //DocType 생성한다.

                                   xmlTxtWriter.WriteDocType("bookstore", null, "books.dtd", null);

 

                                   //주석을 만든다.

                                   xmlTxtWriter.WriteComment("This file represents another fragment of a book store inventory database");

 

                                   //시작 엘리먼트를 생성한다.

                                   xmlTxtWriter.WriteStartElement("book", null);

 

                                   //시작 엘리먼트의 어트리뷰트를 작성한다.

                                   xmlTxtWriter.WriteAttributeString("genre", "autobiography");

                                   xmlTxtWriter.WriteAttributeString("publicationdate", "1979");

                                   xmlTxtWriter.WriteAttributeString("ISBN", "0-7356-0562-9");

 

                                   //시작 엘리먼트 내부에 다른 엘리먼트와 내용을 생성한다.

                                   xmlTxtWriter.WriteElementString("title", null, "The Autobiography of Mark Twain");

 

                                   //시작 엘리먼트 내부에 엘리먼트만 생성한다.

                                   xmlTxtWriter.WriteStartElement("Author", null);

 

                                   //시작 엘리먼트 내부의 엘리먼트에 자식 엘리먼트2개를 생성한다.

                                   xmlTxtWriter.WriteElementString("first-name", "Mark");

                                   xmlTxtWriter.WriteElementString("last-name", "Twain");

 

                                   //엘리먼트를 종료한다.

                                   xmlTxtWriter.WriteEndElement();

 

                                   //시작 엘리먼트 하위에 자식 엘리먼트를 생성한다.

                                   xmlTxtWriter.WriteElementString("price", "7.99");

 

                                   //시작 엘리먼트를 종료한다.

                                   xmlTxtWriter.WriteEndElement();

 

                                   xmlTxtWriter.Flush();

                                   xmlTxtWriter.Close();

    }

}

'General .NET' 카테고리의 다른 글

XML Data  (0) 2007/12/17
XML Readers and Writers  (0) 2007/12/17
C#으로 XML문서 생성하기  (0) 2007/12/17
String.Format 메서드  (0) 2007/12/17
Microsoft .NET Framework 3.0 Programming Model  (0) 2007/12/17
Silverlight (심층적인 웹 환경 구축)  (0) 2007/12/17
Posted by -세티-
2007/12/17 10:20

String.Format 메서드 General .NET2007/12/17 10:20

출처 : http://msdn2.microsoft.com/ko-kr/librar ··· %29.aspx

네임스페이스: System
어셈블리: mscorlib

구문: C#          public static string Format (string format, Object arg0)
        JScript    public static function Format (format : String, arg0 : Object) : String

예제
// This code example demonstrates the String.Format() method.
// Formatting for this example uses the "en-US" culture.

using System;
class Sample
{
    enum Color {Yellow = 1, Blue, Green};
    static DateTime thisDate = DateTime.Now;

    public static void Main()
    {
// Store the output of the String.Format method in a string.
    string s = "";

    Console.Clear();

// Format a negative integer or floating-point number in various ways.
    Console.WriteLine("Standard Numeric Format Specifiers");
    s = String.Format(
        "(C) Currency: . . . . . . . . {0:C}\n" +
        "(D) Decimal:. . . . . . . . . {0:D}\n" +
        "(E) Scientific: . . . . . . . {1:E}\n" +
        "(F) Fixed point:. . . . . . . {1:F}\n" +
        "(G) General:. . . . . . . . . {0:G}\n" +
        "    (default):. . . . . . . . {0} (default = 'G')\n" +
        "(N) Number: . . . . . . . . . {0:N}\n" +
        "(P) Percent:. . . . . . . . . {1:P}\n" +
        "(R) Round-trip: . . . . . . . {1:R}\n" +
        "(X) Hexadecimal:. . . . . . . {0:X}\n",
        -123, -123.45f);
    Console.WriteLine(s);

// Format the current date in various ways.
    Console.WriteLine("Standard DateTime Format Specifiers");
    s = String.Format(
        "(d) Short date: . . . . . . . {0:d}\n" +
        "(D) Long date:. . . . . . . . {0:D}\n" +
        "(t) Short time: . . . . . . . {0:t}\n" +
        "(T) Long time:. . . . . . . . {0:T}\n" +
        "(f) Full date/short time: . . {0:f}\n" +
        "(F) Full date/long time:. . . {0:F}\n" +
        "(g) General date/short time:. {0:g}\n" +
        "(G) General date/long time: . {0:G}\n" +
        "    (default):. . . . . . . . {0} (default = 'G')\n" +
        "(M) Month:. . . . . . . . . . {0:M}\n" +
        "(R) RFC1123:. . . . . . . . . {0:R}\n" +
        "(s) Sortable: . . . . . . . . {0:s}\n" +
        "(u) Universal sortable: . . . {0:u} (invariant)\n" +
        "(U) Universal sortable: . . . {0:U}\n" +
        "(Y) Year: . . . . . . . . . . {0:Y}\n",
        thisDate);
    Console.WriteLine(s);

// Format a Color enumeration value in various ways.
    Console.WriteLine("Standard Enumeration Format Specifiers");
    s = String.Format(
        "(G) General:. . . . . . . . . {0:G}\n" +
        "    (default):. . . . . . . . {0} (default = 'G')\n" +
        "(F) Flags:. . . . . . . . . . {0:F} (flags or integer)\n" +
        "(D) Decimal number: . . . . . {0:D}\n" +
        "(X) Hexadecimal:. . . . . . . {0:X}\n",
        Color.Green);      
    Console.WriteLine(s);
    }
}
/*
This code example produces the following results:

Standard Numeric Format Specifiers
(C) Currency: . . . . . . . . ($123.00)
(D) Decimal:. . . . . . . . . -123
(E) Scientific: . . . . . . . -1.234500E+002
(F) Fixed point:. . . . . . . -123.45
(G) General:. . . . . . . . . -123
    (default):. . . . . . . . -123 (default = 'G')
(N) Number: . . . . . . . . . -123.00
(P) Percent:. . . . . . . . . -12,345.00 %
(R) Round-trip: . . . . . . . -123.45
(X) Hexadecimal:. . . . . . . FFFFFF85

Standard DateTime Format Specifiers
(d) Short date: . . . . . . . 6/26/2004
(D) Long date:. . . . . . . . Saturday, June 26, 2004
(t) Short time: . . . . . . . 8:11 PM
(T) Long time:. . . . . . . . 8:11:04 PM
(f) Full date/short time: . . Saturday, June 26, 2004 8:11 PM
(F) Full date/long time:. . . Saturday, June 26, 2004 8:11:04 PM
(g) General date/short time:. 6/26/2004 8:11 PM
(G) General date/long time: . 6/26/2004 8:11:04 PM
    (default):. . . . . . . . 6/26/2004 8:11:04 PM (default = 'G')
(M) Month:. . . . . . . . . . June 26
(R) RFC1123:. . . . . . . . . Sat, 26 Jun 2004 20:11:04 GMT
(s) Sortable: . . . . . . . . 2004-06-26T20:11:04
(u) Universal sortable: . . . 2004-06-26 20:11:04Z (invariant)
(U) Universal sortable: . . . Sunday, June 27, 2004 3:11:04 AM
(Y) Year: . . . . . . . . . . June, 2004

Standard Enumeration Format Specifiers
(G) General:. . . . . . . . . Green
    (default):. . . . . . . . Green (default = 'G')
(F) Flags:. . . . . . . . . . Green (flags or integer)
(D) Decimal number: . . . . . 3
(X) Hexadecimal:. . . . . . . 00000003

*/

'General .NET' 카테고리의 다른 글

XML Readers and Writers  (0) 2007/12/17
C#으로 XML문서 생성하기  (0) 2007/12/17
String.Format 메서드  (0) 2007/12/17
Microsoft .NET Framework 3.0 Programming Model  (0) 2007/12/17
Silverlight (심층적인 웹 환경 구축)  (0) 2007/12/17
안녕하세요. 세티 입니다.  (0) 2007/12/17
Posted by -세티-
Microsoft .NET Framework 3.0은 Microsoft .NET Framework 2.0, Windows Presentation Foundation, Windows Communication Foundation, 그리고 Windows Wordkflow foundation이 포함된 마이크로소프트 윈도우즈를 위한 모델입니다.

In This Section
Feature Area Overviews
다음의 링크에서 프리젠테이션, 커뮤니케이션, 데이터 마이그레이션과 통합 그리고 보안에 대한 정보
를 찾을 수 있습니다.

.NET Framework Technologies
닷넷 프레임워크 2.0에 새롭게 포함된 것이 어떤 것이 있는지 소개하고 가이드 라인에 대해 볼 수 있습니다.

ASP.NET Web Applications
ASP.NET을 사용하여 생성되는 웹 서비스, 사용자 컨트롤, 웹 어플리케이션을 생성하는 방법들에 관한
정보를 찾을 수 있습니다.
Find information about creating ASP.NET Web applications, developing custom server controls, and XML Web Services created using ASP.NET.

Windows Forms
윈도우즈 폼의 아키텍처, 이벤트, 컨트롤, 데이터 아키텍처, 그래픽 그리고 윈도우즈 폼을 드로잉
하는 정보들에 관해 찾아볼 수 있습니다.

Windows Communication Foundation
윈도우즈 커뮤니케이션 파운데이션을 사용하는 정보에 관해 찾을 수 있습니다.


Windows Presentation Foundation
사용자 인터페이스, 데이터바인딩, 그래픽, 그리고 멀티미디어등을 포함하는 윈도우즈 프리젠테이션 파운데이션 어플리케이션을 빌드하고 배포하는 것에 관한 정보를 찾을 수 있습니다.


Windows Workflow Foundation
윈도우즈 워크플로우 파운데이션에 관한 정보를 찾을 수 있습니다.

Samples
닷넷 프레임워크 3.0 기술을 위한 예제 코드가 있습니다.

.NET Framework 3.0 Tools
닷넷 프레임워크3.0을 타뎃하는 매니지드 어플리케이션과 컴포넌트들을 쉽게 생성하고 배포를 만들기위해 SDK와 Tools을 사용하는 방법에 관한 정보입니다. 일반적으로 참조언어는 참조정보, 컴파일러 참조 그리고 윈도우즈 커뮤니케이션 파운데이션과 윈도우즈 워크플로우 파운데이션 정보를 추가적으로 참조합니다.

Class Library

닷넷 프레임워크 3.0 API 집합내의 모든 공통 클래스들을 위한 신텍스와 예제를 포함합니다.
Posted by -세티-
출처 : 한국마이크로소프트

목차
Silverlight 소개
XAML 개요
XAML 내부
변환, 미디어 및 애니메이션
간단한 Silverlight 응용 프로그램
Silverlight와 서버 응용 프로그램
날씨 응용 프로그램 작성
페이드 인 애니메이션 정의
XAML 서비스 생성
Silverlight 프런트 엔드에 XAML 제공
요약
Microsoft® Silverlight™(이전 코드 이름 "WPF/E")라는 새로운 기술은 차세대 웹 개발을 위한 Microsoft의 전략 중 가장 중요한 요소입니다. Windows® Presentation Foundation 환경을 웹에 구현하기 위해 고안된 Silverlight는 ASP.NET AJAX 등의 다른 웹 개발 환경과 원활하게 조화되는 다양하고 호소력 있는 콘텐츠를 제공합니다.

웹 커뮤니티에 자유롭게 접근하기 위해서는 Silverlight가 여러 상용 운영 체제 및 브라우저에서 성공적으로 실행되어야 합니다. 따라서 최초 릴리스에서는 Windows에서 실행되는 Firefox 및 Internet Explorer®뿐만 아니라 Mac OS X에서 실행되는 Firefox 및 Safari 브라우저를 지원하며 제품이 발전할수록 더 많은 운영 체제 및 브라우저를 지원할 예정입니다. 이러한 기능 외에도 Silverlight는 비디오 재생을 위해 Windows Media® Player를 사용하거나 XAML 구문 분석을 위해 Microsoft .NET Framework 3.0을 사용하지 않는 등 다른 제품에 의존하지 않으며 완전히 독립적입니다.

이 기사에서는 Silverlight 아키텍처의 간략한 개요를 살펴보고 기본적인 Hello World 응용 프로그램부터 시작하여 Silverlight 응용 프로그램 몇 가지를 실제로 작성해 볼 것입니다. 그런 다음 간단한 미디어 플레이어를 만드는 방법에 대해 설명할 것입니다. 또한 Silverlight가 클라이언트 측 기술인데도 PHP 또는 Java를 실행하는 서버와 같이 대규모 서버에 사용하기에 적합한 이유도 알아보겠습니다.


Silverlight 소개

간단히 말해서 Silverlight는 내부 DOM(문서 개체 모델) 및 이벤트 모델을 스크립트 가능한 방식으로 브라우저에 제공함으로써 XAML을 렌더링하는 브라우저 플러그 인입니다. 따라서 디자이너가 그래픽, 애니메이션 및 타임라인을 포함하는 XAML 문서를 구성하면 개발자는 이를 한 페이지 내에 코드로 작성하여 기능을 구현할 수 있습니다. XAML은 XML을 바탕으로 작성되므로 UI를 정의하는 문서는 클라이언트에 텍스트 기반으로 다운로드되며 검색 엔진과 방화벽의 영향을 받지 않습니다. 또한 XAML은 런타임에 서버 응용 프로그램이 구성하고 전송하므로 풍부한 그래픽 환경을 제공할 수 있을 뿐만 아니라 사용자 지정 기능과 동적 기능면에서도 매우 우수합니다.

그림 1에는 UI를 정의하는 정적 XAML 파일과 이벤트 처리를 위해 JavaScript를 사용하는 간단한 Silverlight 응용 프로그램에 대한 분석이 나와 있습니다. 브라우저는 플러그 인을 인스턴스화하고 이 프로세스 중에 XAML 파일을 로드합니다. 파일에 포함된 단추 클릭 등과 같은 이벤트는 브라우저가 캡처하고 JavaScript가 처리합니다. Silverlight 콘텐츠의 DOM이 제공되므로 JavaScript 코드가 Silverlight 콘텐츠를 동적으로 업데이트하여 렌더링된 콘텐츠의 상태를 변경할 수도 있습니다.

그림 1 샘플 응용 프로그램
그림 1 샘플 응용 프로그램

그림 2에는 Silverlight 응용 프로그램을 지원하는 아키텍처가 나와 있습니다. 주 프로그래밍 인터페이스는 JavaScript DOM API입니다. 이 인터페이스를 사용하면 콘텐츠의 로드 완료 또는 애니메이션 완료 등과 같이 Silverlight XAML 내에서 발생하는 이벤트에 응답할 수 있습니다. 또한 메서드를 호출하여 애니메이션 시작 또는 비디오 재생 일시 정지와 같은 프레젠테이션을 조작할 수도 있습니다. 이러한 기능은 XAML 구문 분석 엔진을 기반으로 합니다. 파서는 XAML에 정의된 그래픽 및 애니메이션의 렌더링을 처리하는 프레젠테이션 코어를 위해 메모리 내에 XAML DOM을 생성합니다. 또한 런타임에는 WMV, WMA 및 MP3 멀티미디어 콘텐츠 재생에 필요한 코덱이 들어 있습니다.

그림 2 Silverlight 아키텍처
그림 2 Silverlight 아키텍처

마지막으로 런타임에는 렌더링 처리를 관리하는 프레젠테이션 코어가 들어 있습니다. 프레젠테이션 런타임은 앞에서 설명한 대로 Windows, Mac OS X 등 여러 운영 체제의 다양한 브라우저를 지원하는 브라우저 플러그 인에 기본 제공되어 있습니다. 따라서 독립적인 그래픽 및 미디어 렌더링 엔진을 브라우저에 연결하고 JavaScript를 통해 스크립팅할 수 있습니다.

Back to top

XAML 개요

XAML은 그래픽 요소, 사용자 인터페이스, 동작, 애니메이션 등을 정의하는 데 사용되는 XML 기반 언어입니다. 이는 Microsoft의 .NET Framework 3.0에 포함된 데스크톱 지향 기술인 Windows Presentation Foundation용 태그 언어로서 처음 도입되었으며 응용 프로그램 생성 시 디자이너와 개발자 간 작업에 교량 역할을 하기 위해 고안되었습니다.

지금까지는 응용 프로그램을 만들기 위해 디자이너가 사용하는 도구 및 리소스 모음이 개발자가 사용하는 것과 달랐으며 이러한 차이는 결과 응용 프로그램에도 부정적인 영향을 줄 여지가 있었습니다. Microsoft는 디자인 전문가들이 그래픽 항목과 사용자 인터페이스를 개별적으로 구성하여 최종 결과를 XAML로 표현하면 이를 통해 개발자가 응용 프로그램을 구축할 수 있도록 Microsoft Expression® 및 Microsoft Expression Blend라는 새 Expression 도구 모음을 도입했습니다.

Silverlight의 최초 릴리스에 사용된 XAML은 데스크톱에 사용할 수 있는 완벽한 XAML의 웹 지향 하위 집합이므로 Windows Presentation Foundation에 사용된 XAML과는 차이가 있습니다. 따라서 Windows Presentation Foundation XAML에 익숙하다면 Silverlight XAML에 <Window> 태그, 페이지 리소스, 데이터 바인딩, 유용한 컨트롤 모델 등과 같은 기능이 없음을 알 수 있습니다.

XAML에서는 XML 태그를 사용하여 요소를 정의합니다. 각 Silverlight 문서의 루트 수준에는 UI 요소가 그려질 공간을 정의하는 Canvas 태그가 위치합니다. 이 Canvas에는 Silverlight에 필요한 XML 네임스페이스 선언이 들어 있습니다.

<Canvas
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”>
</Canvas>

Canvas는 고유한 자식을 생성할 수 있는 자식 Canvas 등을 포함해 둘 이상의 자식을 가질 수 있습니다. 자식 Canvas의 위치는 부모 Canvas를 기준으로 상대적으로 지정되며 루트 Canvas만 예외입니다. 다음은 부모(Canvas)의 왼쪽 위 모서리에서 25픽셀 떨어진 곳에 위치한 사각형을 포함하는 Canvas의 예입니다.

<Canvas Width=”250” Height=”200”>
  <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
       Width=”200” Height=”150” Fill=”Black” />
</Canvas>
Back to top

XAML 내부

Silverlight XAML은 다양한 도형을 지원하므로 이를 조합하여 복잡한 형태를 만들 수 있습니다. 기본 지원 도형에는 사각형(Rectangle), 타원(Ellipse), 선(Line), 다각형(Polygon), 다중선(PolyLine), 경로(Path)가 있습니다. 이름만으로도 모양을 쉽게 짐작할 수 있을 것입니다. 다중선은 연결된 줄 세그먼트를 정의하는 데 사용되며 경로는 Canvas에서 비선형 경로(예: 자유 곡선)를 정의하는 데 사용됩니다.

브러시는 화면에 개체를 어떻게 그릴지 정의합니다. Fill 명령을 사용하면 브러시의 내부가 채워지며 Stroke 명령을 사용하면 브러시의 윤곽선을 그릴 수 있습니다. 브러시에는 단색 브러시, 그라데이션 브러시 및 이미지 브러시가 있습니다. 단색 브러시는 앞서 예제에서 사용한 Fill="Black"과 같이 Fill 특성에 고정 색상을 지정하거나 다음과 같이 SolidColorBrush 속성을 연결하여 구현할 수 있습니다.

   <Rectangle Canvas.Top=”25” Canvas.Left=”25” 
          Width=”200” Height=”150”>
      <Rectangle.Fill>
         <SolidColorBrush Color=”Black” />
      </Rectangle.Fill>
   <Rectangle>

색상은 이름(141가지 색상 이름 지원) 또는 16진수 RGB로 정의할 수 있습니다.

그라데이션 브러시는 표준 좌표 공간에서 그라데이션 범위 및 그라데이션 중지 지점을 지정함으로써 구현할 수 있습니다. 예를 들어 선형 그라데이션의 방향을 오른쪽에서 왼쪽으로 이동하고 색상이 검정에서 점점 흰색으로 변경되도록 설정한다고 가정하면 검정인 0(직선의 시작)에 그라데이션 중지점을 하나 지정하고 흰색인 1(직선의 끝)에 또 다른 그라데이션 중지점을 지정할 수 있습니다. 그러면 Silverlight가 그라데이션을 그립니다. 2차원 공간에 정사각형을 정의하여(0: 왼쪽 위, 1: 오른쪽 아래) 그라데이션을 그릴 수도 있습니다. 따라서 왼쪽 위 빨강에서 오른쪽 아래 검정으로 2차원의 그라데이션이 적용된 사각형을 정의하려면 다음과 같이 XAML을 사용합니다.

<Rectangle Width=”200” Height=”150” >
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint=”0,0” EndPoint=”1,1”>
      <LinearGradientBrush.GradientStops>
        <GradientStop Color=”Red” Offset=”0” />
        <GradientStop Color=”Black” Offset=”1” />
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle>

ImageBrush를 사용하여 개체를 그릴 수도 있으며, 이때 이미지는 크기에 맞게 적절히 잘리거나 늘어나게 됩니다. 예를 들어 다음과 같은 XAML을 사용하여 ImageBrush를 통해 타원을 채우도록 지정할 수 있습니다.

<Ellipse Width=”200” Height=”75” >
  <Ellipse.Fill>
    <ImageBrush ImageSource=”http://.../logo.jpg” /> 
  </Ellipse.Fill>
</Ellipse>

XAML에서 TextBlock 태그를 사용하면 텍스트를 렌더링할 수 있으며 내용, 글꼴, 크기, 래핑과 같은 텍스트의 요소를 제어할 수 있습니다. 다음은 이와 관련된 예입니다.

<TextBlock>Hello</TextBlock>

<TextBlock FontSize=”18”>Hello</TextBlock>

<TextBlock FontFamily=”Courier New”>Hello</TextBlock>

<TextBlock TextWrapping=”Wrap” Width=”100”>
  Hello there, how are you?
</TextBlock>

이 밖에도 Silverlight는 텍스트 입력을 구현하는 데 사용되는 키보드 이벤트를 지원합니다. 루트 요소에서 키보드 이벤트(KeyDown 또는 KeyUp)를 정의하고 이벤트 인수를 사용하여 어떤 키가 눌러졌는지 추적할 수 있습니다.

Back to top

변환, 미디어 및 애니메이션

XAML을 사용하여 개체에 대해 여러 가지 변환을 정의할 수 있습니다. RotationTransform은 정의된 각도로 요소를 회전하며, ScaleTransform은 개체를 늘이거나 줄이는 데 사용됩니다. SkewTransform은 개체를 정의된 방향으로 지정된 각도만큼 기울이고, TranslateTransform은 정의된 백터에 따라 개체를 이동합니다. MatrixTransform은 이러한 모든 변환을 적용할 수 있습니다.

변환을 그룹화하여 하나의 개체에 여러 가지 변환을 정의할 수 있습니다. 그림 3에는 그 예가 나와 있습니다. 이 예에서는 Canvas에 타원이 세 개 있습니다. Canvas 수준에서 변환을 정의하면 각 타원이 회전하거나 크기가 변경되게 됩니다.

오디오 및 비디오 콘텐츠는 MediaElement 태그를 사용하여 제어할 수 있습니다. 이러한 태그에는 재생할 미디어를 지정하는 source 특성이 들어 있습니다. 이 태그를 사용하여 정의된 개체는 미디어 재생을 제어하는 다양한 메서드 및 이벤트를 제공합니다. XAML을 사용하여 빌드되고 JavaScript를 통해 사용자 상호 작용(재생, 일시 정지, 중지 등)이 가능한 간단한 미디어 플레이어의 예는 이 기사 뒷부분에서 설명합니다. MediaElement의 정의 방법은 간단합니다.

<Canvas xmlns=”...” xmlns:x=”...”>
   <MediaElement Source=”xbox.wmv” /> 
</Canvas>

XAML의 애니메이션은 타임라인 동안에 변경되는 속성을 정의함으로써 구현됩니다. 애니메이션 정의는 Storyboard 내에 저장됩니다. 애니메이션의 종류에는 숫자 속성을 변경하는 DoubleAnimation, 색상 및 브러시를 변경하는 ColorAnimation 및 2차원 값을 변경하는 PointAnimation 등 여러 가지가 있습니다. 이러한 애니메이션은 선형 또는 키프레임 기반으로 만들 수 있습니다. 선형 애니메이션의 경우 정의된 타임라인에 따라 애니메이션이 서서히 변경됩니다. 키프레임 기반 애니메이션을 사용하면 애니메이션이 각 값에 따라 변경될 수 있습니다.

그림 4에는 시간이 지남에 따라 원의 너비가 변경되는 간단한 애니메이션에 대한 예가 나와 있습니다. AutoReverse 속성이 True로 설정되어 있으므로 원의 너비가 커졌다가 작아지는 변환만 반복하는 것이 아니라 커졌다가 작아졌다가 다시 커지는 애니메이션이 반복됩니다.

Back to top

간단한 Silverlight 응용 프로그램

Visual Studio 2005에서 Silverlight용 응용 프로그램 템플릿(Silverlight SDK 다운로드에 포함됨)을 사용하여 Silverlight용 응용 프로그램을 쉽게 빌드할 수 있습니다. 이 기사에서 필자는 Visual Web Developer™ Express 응용 프로그램을 사용했습니다. 이 응용 프로그램은 MSDN®에서 다운로드할 수 있습니다.

다음 예는 WMV 비디오 콘텐츠를 재생하는 매우 간단한 미디어 플레이어입니다. 이 예에서는 Channel 9 비디오(channel9.msdn.com)를 사용하지만 원하는 비디오로 변경하여 재생할 수 있습니다. XAML은 상당히 간단하며 그림 5에서 전체 내용을 볼 수 있습니다. 작업을 단순화하기 위해 Play, Stop 및 Pause 단추에는 TextBlock 요소가 사용됩니다.

MediaElement 태그는 비디오를 정의하는 데 사용됩니다. 이름은 mPlayer이며 크기는 640×400으로 설정했습니다. Source 태그에는 Microsoft 웹 사이트의 다운로드 항목으로 호스팅되어 있는 WMV 비디오가 지정되어 있습니다.

다음은 Play, Stop 및 Pause 단추를 정의하는 데 사용되는 세 개의 TextBlock 요소입니다. 이러한 단추는 Canvas의 왼쪽 위에 수직으로 배치됩니다. Canvas.Left는 설정되어 있지 않으므로 기본값인 0이 적용됩니다. 세 개의 TextBlock 요소에는 클릭될 때 실행될 JavaScript 이벤트 처리기인 MouseLeftButtonDown이 정의되어 있습니다. 단추를 마우스로 클릭하면 Silverlight에서 브라우저로 이벤트를 보내고 여기서 JavaScript가 이벤트를 캡처한 후 처리합니다.

이제 이 XAML을 사용하는 응용 프로그램을 완성하기 위해 Visual Web Developer Express에서 JavaScript 이벤트 처리기를 구현해 보겠습니다. 이 이벤트 처리기가 작동하려면 silverlight.js 파일이 필요합니다. 이 파일은 Silverlight용 SDK 다운로드에서 구하거나 MSDN 샘플 다운로드 사이트의 Silverlight 샘플에서 얻을 수 있습니다.

Visual Web Developer Express를 사용하여 새 웹 사이트를 만듭니다. 이 사이트 내에 \js라는 폴더를 만들고 생성된 폴더에 silverlight.js 파일을 추가합니다. \js 폴더를 마우스 오른쪽 단추로 클릭하고 새 항목 추가를 선택합니다. 새 파일 대화 상자에서 JScript 파일을 선택하고 eventhandlers.js로 이름을 변경합니다.

다음은 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 새 항목 추가를 클릭한 후 videoplayer.xaml이라는 새 XML 파일을 만듭니다. 그림 5와 같은 XAML을 입력합니다.

마지막으로 프로젝트에 새 HTML 페이지를 추가하고 Default.htm으로 이름을 변경합니다. JavaScript 라이브러리를 로드하고 로드한 라이브러리를 사용하여 Silverlight 플레이어의 인스턴스를 생성함으로써 XAML 콘텐츠를 렌더링할 수 있도록 HTML 페이지를 편집합니다. 그림 6은 Default.htm의 전체 소스 코드를 보여 줍니다.

페이지 맨 위의 스크립트 태그에서는 JavaScript 라이브러리, silverlight.js 및 eventhandlers.js를 가져옵니다. silverlight.js 라이브러리는 Silverlight 플러그 인의 다운로드 및 인스턴스화를 관리합니다. 이 라이브러리에는 브라우저 및 OS가 추상화되어 포함되어 있기 때문에 이에 대한 걱정 없이 Sys.Silverlight.createObjectEx 기능을 사용하여 새 Silverlight 컨트롤을 구현할 수 있습니다. Silverlight 플러그 인 자체는 ID가 지정된 DIV 블록 내에 있어야 합니다. 이 예의 경우 플러그 인이 들어 있는 DIV는 AgControl1Host입니다. Silverlight 콘텐츠를 인스턴스화할 때 이 ID를 사용할 것입니다.

Silverlight 컨트롤의 새 인스턴스를 생성하고 생성된 인스턴스를 구성할 다양한 매개 변수를 전달함으로써 Silverlight 플러그 인을 인스턴스화할 수 있습니다. 이러한 매개 변수에 대한 자세한 내용은 Silverlight SDK를 참조하십시오.

마지막 단계로, Play, Stop 및 Pause 단추 클릭 시 발생하는 이벤트를 처리할 JavaScript 기능을 구현해야 합니다. 이 코드는 eventhandlers.js에 들어 있어야 합니다.

function PlayVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Play();
}
function PauseVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Pause();
}
function StopVideo(sender,args)
{
   var mPlayer = sender.findName(“mPlayer”);
   mPlayer.Stop();
}

XAML의 Stop TextBlock에서 MouseLeftButtonDown 특성을 JavaScript:StopVideo로 지정합니다. Sender 및 Args 매개 변수를 사용하는 동일한 이름의 JavaScript 함수를 만들어 기능을 구현합니다. Silverlight에서 findName 함수를 사용하면 DOM 내에서 지정된 매개 변수와 일치하는 요소를 검색할 수 있습니다. 따라서 비디오 재생을 중지하려면 findName API를 사용하여 MediaElement를 검색합니다. XAML에서 이 요소의 이름은 mPlayer입니다. findName API가 이 개체에 대한 참조를 반환하면 이러한 참조를 JavaScript 변수에 로드할 수 있습니다. 이제 참조가 있으므로 비디오 중지를 재생하기 위해 Stop 메서드를 호출하기만 하면 됩니다. Play(재생) 및 Pause(일시 정지) 기능의 작동 원리는 유사합니다.

이제 끝났습니다. 간단한 비디오 플레이어가 즉시 Silverlight를 통해 생성됩니다. 응용 프로그램을 실행하면 그림 7과 같은 화면이 표시됩니다.

그림 7 간단한 비디오 플레이어
그림 7 간단한 비디오 플레이어 (더 크게 보려면 이미지를 클릭하십시오.)

이러한 방법은 비디오의 URI를 XAML에 하드코딩하려는 경우에는 매우 적합하지만 일반적으로 사용할 수 있는 방법은 아닙니다. 이러한 정적 HTML 페이지를 변경하여 비디오를 매개 변수로 받을 수 있는 Web Form으로 변경해 보겠습니다.

첫 번째 단계는 XAML에서 미디어 파일에 대한 참조를 제거하는 것입니다. XAML에서 MediaElement를 변경하여 Source 특성을 제거합니다. 제거를 마친 XAML은 다음과 같습니다.

<MediaElement x:Name=”mPlayer” Width=”640” Height=”400”/>

그런 다음 응용 프로그램에서 VideoPlayer.aspx라는 새 Web Form(ASPX)을 만듭니다. 이 Web Form은 그림 6과 같이 videoplayer.xaml이라는 소스가 포함된 Silverlight 컨트롤을 인스턴스화해야 합니다. 또한 다음과 같은 JavaScript 코드도 포함해야 합니다.

<script type=”text/javascript”>
  function root_Loaded(sender,args) {
    var mPlayer = sender.findName(“mPlayer”);
    mPlayer.Source =
      “<% Response.Write(Request.Params[“VideoURI”]); %>”;
    mPlayer.Play();
}
</script>

XAML에는 Canvas가 로드할 때 실행될 이벤트에 대한 이벤트 선언이 들어 있습니다. 이러한 이벤트 선언은 JavaScript의 root_Loaded 이벤트 처리기에서 캡처합니다. 이 함수는 ASP.NET을 사용하여 서버의 HTTP 요청에서 VideoURI를 분리하고 이 VideoURI를 JavaScript 함수에 넣어 비디오 소스를 설정합니다. 페이지를 실행하면 Silverlight에서 VideoURI 매개 변수의 비디오를 렌더링합니다. 이 예는 너무 간단해서 오류 처리 또는 필터링이 없으므로 응용 프로그램에 이러한 유형의 기능을 제공하려면 별도로 추가해야 합니다.

URI를 사용하여 이 페이지를 호출하면 다음과 같이 됩니다.

http://localhost/MSDN1/
VideoPlayer.aspx?videouri=xbox.wmv

ASP.NET은 JavaScript 블록이 들어 있는 다음과 같은 페이지를 내보냅니다.

   <script type=”text/javascript”>
     function root_Loaded(sender,args)
     {
       var mPlayer = 
         sender.findName(“mPlayer”);
       mPlayer.Source = “xbox.wmv”;
       mPlayer.Play();
     }
   </script>

그런 다음 이 JavaScript가 MediaElement로 xbox.wmv 파일을 로드하고 Silverlight가 비디오를 재생합니다. 이를 통해 서버 측 활성 페이지(ASPX, PHP 또는 Java)를 보다 유연하게 만들면 Silverlight 최종 사용자 환경을 크게 개선할 수 있음을 알 수 있습니다.

Back to top

Silverlight와 서버 응용 프로그램

Silverlight를 단순히 브라우저에 풍부한 콘텐츠를 포함하기 위한 클라이언트 기술로 생각하면 안 됩니다. 풍부한 컨텐츠는 Java Applet, ActiveX® 컨트롤 또는 Flash 응용 프로그램 등으로 구축된 닫힌 플러그 인을 통해서도 가능합니다. 반면 Silverlight는 UI가 텍스트 기반 XAML로 정의되어 있고 JavaScript를 통해 프로그래밍 기능이 구현되므로 열린 기술입니다. 이를 통해 개발자들은 백 엔드 서버와 상호 작용 할 수 있는 응용 프로그램을 쉽게 구축할 수 있습니다.

예를 들어 날씨 응용 프로그램을 생각해 보면 클라이언트 측에서 날씨 응용 프로그램을 만들려는 경우에는 웹 서비스를 사용하는 Java applet, ActiveX 컨트롤 또는 Flash 응용 프로그램을 빌드한 다음 이러한 애플릿을 클라이언트에 배포할 수 있습니다. 하지만 이렇게 되면 클라이언트와 서버 간 통신 요구가 증가하게 됩니다. 만약 이러한 데이터가 유료 구독 서비스라면 어떨까요? 응용 프로그램을 배포한 사람은 데이터 서비스에 액세스하는 클라이언트에 대한 라이센스 승인 작업을 하느라 도메인 관련 비즈니스 논리를 빌드할 시간이 없을 것입니다.

하지만 서버 측에서 응용 프로그램을 구성하고 모든 데이터를 클라이언트로 전달할 수 있다면 이러한 작업에 대한 부담을 덜 수 있을 것입니다. Expression Blend와 같은 도구를 사용하면 응용 프로그램의 사용자 인터페이스를 위한 템플릿을 XAML로 구성하고 표현할 수 있습니다. 그러면 런타임에 개발자가 관련 데이터를 가져와 템플릿에 삽입하고 완성된 XAML을 클라이언트로 반환하면 클라이언트에서 XAML을 렌더링합니다. 클라이언트 측에서는 논리 또는 연결(물론 초기 연결된 서버는 제외)이 필요하지 않기 때문에 클라이언트의 배포 및 관리는 상대적으로 수월하게 됩니다.

Back to top

날씨 응용 프로그램 작성

이 섹션에서는 날씨 응용 프로그램을 구현하는 간단한 XAML 파일(그림 8 참조)을 작성하는 방법에 대해 알아보겠습니다. 완성된 날씨 응용 프로그램은 응용 프로그램의 브라우저 내 주소에 매개 변수로 전달된 특정 우편 번호에 대한 3일간의 기온 예보를 렌더링하게 됩니다. 또한 날씨, 정확한 날짜, 우편 번호로 지정된 위치 이름 및 날씨 데이터 애니메이션을 그래픽으로 표현하여 렌더링합니다. 날씨 응용 프로그램에 대한 모든 XAML 목록은 MSDN Magazine 웹 사이트에서 볼 수 있습니다.

그림 8 Silverlight 날씨 응용 프로그램
그림 8 Silverlight 날씨 응용 프로그램 (더 크게 보려면 이미지를 클릭하십시오.)

문서의 맨 위에는 여는 Canvas 태그가 위치합니다. 이는 개체가 그려지는 기본 컨테이너입니다. 하나의 Canvas에 국한되지 않으므로, Canvas를 사용하여 관련 요소를 모두 그룹화할 수 있습니다. 따라서 각 날짜에 그래픽, 최고 기온, 최저 기온 및 다양한 레이블이 포함되고 이 모든 데이터가 하나의 XAML 템플릿으로 수집됩니다. 그림 9는 특정 날짜에 대한 예가 나와 있습니다. 이 예에서는 Canvas에 다양한 TextBlock 및 Image 컨트롤이 들어 있습니다. 이 Canvas의 이름은 cnv2로 지정되어 있고 불투명도가 0(즉 처음에는 보이지 않음)인 화면에 위치하고 있습니다. Canvas가 화면의 특정 위치에 오도록 높이, 너비, 왼쪽 및 맨 위 값이 설정되어 있습니다.

TextBlock은 Silverlight에서 텍스트를 렌더링하는 데 사용됩니다. TextBlock에는 여러 가지가 있는데, lblDegHigh2 및 lblDegLow2라는 TextBlock에 저장된 "°F" 레이블과 같이 하드코딩된 레이블로 사용되는 것도 있습니다.

lblDate2, lblHigh2 및 lblLow2라는 TextBlock에는 자리 표시자 정보가 들어 있습니다. 이 예에서는 이러한 TextBlock이 특정 데이터 및 온도로 하드코딩되었지만 ASP.NET 코드에서는 이러한 정보가 지정된 우편 번호에 해당하는 실제 날짜 및 온도로 다시 정의됩니다.

Back to top

페이드 인 애니메이션 정의

Canvas 노드는 이벤트에 대한 작업을 실행하는 트리거를 지원합니다. 이 예에서는 다음과 같이 Canvas.Triggers가 페이지가 로드될 때 발생하도록 지정되어 있습니다.

<Canvas.Triggers>
  <EventTrigger RoutedEvent=”FrameworkElement.Loaded”>
    <BeginStoryboard>
...

따라서 페이지가 로드되면 트리거가 발생하고 애니메이션 스토리보드가 시작됩니다. 애니메이션 스토리보드는 애니메이션 동작을 지정합니다. 다음은 cnv1이라는 Canvas(특정 날짜의 날씨에 대한 텍스트 자리 표시자 및 그래픽 포함)에 사용된 애니메이션입니다.

<DoubleAnimationUsingKeyFrames BeginTime=”00:00:00”  
    Storyboard.TargetName=”cnv1” 
    Storyboard.TargetProperty=”(UIElement.Opacity)”>
  <SplineDoubleKeyFrame KeyTime=”00:00:00” Value=”0”/>
  <SplineDoubleKeyFrame KeyTime=”00:00:01” Value=”1”/>
</DoubleAnimationUsingKeyFrames>

애니메이션 유형은 DoubleAnimationUsingKeyFrames입니다. Canvas 및 자식 Canvas의 불투명도(UIElement.Opacity에 지정됨)를 0에서 1로 수정하여 일정한 시간 동안 페이드 인하도록 할 수 있습니다. 시간은 애니메이션과 관련된 키프레임을 통해 정의합니다.

XAML이 렌더링되면 스토리보드가 시작되어 첫 번째 요소가 렌더링 시작(0초) 후 1초 사이에 불투명도 0에서 1로 페이드 인하도록 합니다. XAML을 보면 다른 Canvas들이 1초와 2초 사이, 2초와 3초 사이에 각각 페이드 인하여 차례로 표시되는 사실을 알 수 있습니다.

XAML은 유효한 XML 형식이기 때문에 요소에 특성을 명명할 수 있으며 이를 통해 요소를 호출할 수 있습니다. 예를 들어 하루 최고 기온에 대한 자리 표시자 요소는 다음과 같습니다.

<TextBlock x:Name=”lblHigh1” Width=”67” Height=”59” 
        Canvas.Left=”112” Canvas.Top=”30” FontFamily=”Tahoma” 
        FontSize=”48” FontWeight=”Bold” Foreground=”#FFF64F12” 
        Text=”27” TextWrapping=”Wrap”/>

이 TextBlock는 lblHigh1이라는 이름으로 지정됩니다. 다음 단계에 나타나게 되는 서비스는 XMLDocument를 사용하여 템플릿 XAML을 로드하고 lblHigh1이라는 이름이 지정된 노드를 검색하여 다음과 같은 C# 코드로 텍스트 속성을 변경합니다.

string xpath = “//d:TextBlock[@x:Name=’lblHigh1’]”;
xNode = xmlDoc.SelectSingleNode(xpath, mng);
string high = myResults[n - 1].MaxTemperatureF;
xNode.Attributes[“Text”].Value = high;
Back to top

XAML 서비스 생성

웹 페이지에서 Silverlight를 실행하면 컨트롤이 획득한 매개 변수 중 하나가 렌더링할 XAML의 위치입니다. 이때 XAML은 동적 언어로, 날씨가 요청되는 우편 번호에 따라 변경됩니다. 따라서 XAML을 생성하고 반환하는 웹 응용 프로그램을 만들면 XAML을 렌더링하는 페이지가 이러한 웹 페이지를 참조하게 됩니다. 이는 이러한 Silverlight 응용 프로그램을 구축하기 위한 첫 단계입니다.

Visual Studio®를 사용하여 새 웹 프로젝트를 만듭니다. 앞서 비디오 플레이어에서와 같이 \js 폴더를 만들고 생성된 폴더에 silverlight.js 파일을 추가합니다. 다음에 정의된 웹 서비스를 참조하는 프로젝트에 새 웹 참조를 추가합니다.

http://www.webservicex.net/WeatherForecast.asmx?WSDL

서비스의 이름을 weatherservice로 지정합니다. 프로젝트에 새 Web Form을 추가하고 Web Form XAMLSource.aspx를 호출합니다. Add Code as a Separate Page(별도의 페이지로 코드 추가) 옵션을 선택합니다. 코드 페이지의 맨 위에 다음과 같은 지시문이 있는지 확인합니다.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.XPath;

XAMLSource.aspx의 Page_Load 이벤트 처리기에 코드를 추가하는 방법은 이 섹션의 뒷부분에서 설명하겠습니다. 일단 XMLDocument 개체에 Scene.xaml이라는 템플릿을 로드합니다.

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath(“Scene.xaml”));

다음은 읽기 매개 변수를 설정합니다. 페이지 호출 시 필요한 우편 번호를 지정하는 쿼리 문자열 매개 변수를 사용하게 됩니다.

http://server/XamlSource.aspx?ZIP=<something>

매개 변수를 가져오려면 다음 코드를 사용합니다.

string strZip = “98052”;
if (Request.Params[“ZIP”] != null)
    strZip = Request.Params[“ZIP”];

이 코드는 쿼리 문자열을 시작하여 매개 변수화된 우편 번호를 로컬에 저장하며, 이러한 쿼리 문자열이 HTTP 요청으로 전달되지 않은 경우에는 기본값이 설정됩니다. 그런 다음 날씨 정보를 제공하는 웹 서비스에 대한 호출을 생성합니다.

weatherservice.WeatherForecast myWeather = new 
    weatherservice.WeatherForecast();

weatherservice.WeatherForecasts myForecast =   
    myWeather.GetWeatherByZipCode(strZip);

weatherservice.WeatherData[] myResults = myForecast.Details;

이 코드는 웹 서비스 프록시의 인스턴스(Visual Studio에서 서비스의 WSDL에 참조를 추가하면 생성됨)를 생성하여 myWeather를 호출합니다. 웹 서비스는 WeatherForecasts 데이터 구조에 있는 데이터를 반환하므로 서비스의 GetWeatherByZipCode 메서드 호출을 통해 이러한 데이터 구조의 인스턴스(myForecast)를 생성한 후 문자열을 전송합니다. forecast 개체의 Details 멤버는 WeatherData 유형의 배열이므로 변수 myResults는 이러한 개체의 인스턴스로 설정됩니다.

다음 단계는 검색을 위해 XPath를 사용하여 XMLDocument를 초기화하는 것입니다. XML은 일부 요소(x:Name와 같이 x 접두사가 붙은 요소)에 대한 네임스페이스로 XAML 스키마를 사용하므로 페이지에서 접두사가 붙지 않은 요소를 포함해 모든 요소에 대한 네임스페이스를 정의해야 합니다. 예를 들어 XPath //TextBlock과 일치하는 노드는 검색할 수 없지만 기본 네임스페이스에 새 접두사, 이 예의 경우 더미(dummy)를 뜻하는 d를 지정한 후 이러한 접두사를 사용하여 기본 노드를 검색하면 //d:TextBlock을 검색할 수 있습니다. 코드는 다음과 같습니다.

NameTable myn = new NameTable();
XmlNamespaceManager mng = new XmlNamespaceManager(new NameTable());
mng.AddNamespace(“d”,
    “http://schemas.microsoft.com/winfx/2006/xaml/presentation”);
mng.AddNamespace(“x”, “http://schemas.microsoft.com/winfx/2006/xaml”);

XPath를 사용할 수 있으므로 마을 이름이 들어 있는 노드를 검색하여 Text 속성을 우편 번호로 식별되는 서비스로 마을 이름으로 변경할 수 있습니다.

XmlNode xNode = xmlDoc.SelectSingleNode(
    “//d:TextBlock[@x:Name=’lblTownName’]”, mng);

xNode.Attributes[“Text”].Value = 
    myForecast.PlaceName + “,” + myForecast.StateCode;

마찬가지로 그림 10에 나와 있는 코드를 사용하여 3일 동안 원하는 위치가 들어 있는 자리 표시자 노드 값을 검색하고 XML에 올바른 값을 입력할 수 있습니다.

XML 문서에 템플릿과 올바른 데이터를 완벽하게 채웠으므로 호출자에게 이를 반환하기만 하면 됩니다. 이 작업은 다음과 같이 MIME 유형을 설정하고 응답 스트림에 XMLDocument 개체의 콘텐츠를 바로 작성하여 수행합니다.

Response.ContentType = “text/xml”;
Response.Write(xmlDoc.InnerXml);

그런 다음 Visual Studio에서 ASPX 페이지에 제공한 자리 표시자 HTML을 제거합니다. ASPX 파일에서 첫 번째 줄을 제외하고 모두 제거합니다. 제거를 마친 코드는 다음과 같습니다.

<%@ Page Language=”C#” AutoEventWireup=”true”    
         CodeFile=”XamlSource.aspx.cs” Inherits=”_Default” %>

마지막 단계는 솔루션에 새 XML 파일을 추가하고 Scene.xaml으로 이름을 변경하는 것입니다. 이전 코드에서 이 파일이 참조된 것을 보았을 겁니다. 전체 날씨 XAML을 가져와서 이 파일에 붙여넣습니다. 이제 페이지를 실행하면 XAMLSource.aspx 페이지에서 반환된 XAML이 브라우저에 표시됩니다.

Back to top

Silverlight 프런트 엔드에 XAML 제공

이전 단계에서는 템플릿 XAML을 빌드하고 웹 서비스를 사용하는 Web Form에 이러한 XAML을 포함한 다음 웹 서비스 호출에 대한 결과를 XAML의 올바른 위치에 넣었습니다. 이제 Silverlight 컨트롤이 들어 있는 페이지를 제공하고 이러한 XAML 서비스에 지정해야 합니다.

이전 섹션에서 사용한 웹 사이트를 열고 Default.aspx라는 새 Web Form을 추가합니다. Default.aspx의 HTML 코드를 그림 11과 같이 수정합니다.

여기서 중요한 부분은 Silverlight.createObjectEx에 대한 호출로, 정적 videoplayer.xaml이 XAML 소스 응용 프로그램에 대한 호출로 바뀜으로써 이러한 Default.aspx 페이지가 우편 번호 식별을 위해 받은 매개 변수를 XAML 소스 응용 프로그램에 전달한다는 점입니다.

“WeatherSite/XamlSource.aspx?ZIP=<%
    if (Request.Params[“ZIP”] == null)
        Response.Write(“98052”);
    else
        Response.Write(Request.Params[“ZIP”]);
%>” 

이 코드는 페이지에 요청 매개 변수를 가져와 URL에 추가하여 마지막 단계에서 생성된 XamlSource 페이지를 호출합니다. 그런 다음 XamlSource를 호출하여 우편 번호를 전송하고 Silverlight에서 렌더링할 XAML 문서를 얻습니다. Default.aspx?ZIP=90210의 실행 결과는 그림 8에 나와 있습니다.

Back to top

요약

이 기사에서는 Silverlight에 대해 자세히 소개했습니다. 또한 단순히 "Hello, World"라는 응용 프로그램만 설명하지 않고 XAML을 사용하여 사용자 인터페이스를 생성하는 방법, XAML을 JavaScript에 연결하여 상호 작용하는 방법, 단순한 클라이언트 패러다임에서 벗어나 서버 기반 패러다임으로 이동하여 응용 프로그램의 유연성을 높이는 방법 등 다른 응용 프로그램에 대해서도 살펴보았습니다. 이러한 방법론을 사용하여 비디오 스트림의 URI를 받아 재생하고, 블로그 등에서 사용하기에 적합한 간단한 비디오 플레이어를 생성하는 방법도 알아보았습니다.

또한 매우 간단한 클라이언트 배포 모델이 포함된 날씨 모니터 형태로 구현된 데이터 인식 응용 프로그램을 빌드하는 방법도 살펴보았습니다. Silverlight 구성 요소를 통해 서버에서 간단히 올바른 XAML을 호출하여 이를 렌더링함으로써 풍부하면서도 간편한 클라이언트를 만들어 보았습니다.

ASP.NET 및 Microsoft 스택은 이와 같은 웹 응용 프로그램을 빌드하는 데 매우 생산적인 플랫폼 중 하나이지만 이 기사의 다운로드에는 이러한 응용 프로그램의 Java 버전도 들어 있습니다. 이 버전은 ASP.NET 버전과 동일하게 웹 서비스를 사용하여 데이터를 얻은 다음 XML 문서 DOM에 XAML을 로딩하는 기능을 제공합니다. 그런 다음 템플릿 데이터에 해당하는 노드를 찾아 이러한 노드 값을 웹 서비스 노드 값으로 변경한 후 완성된 XAML을 URI로 작성합니다. 그런 후에 JSP(코드는 생략)를 생성하여 이러한 서블릿의 URL을 참조한 후 Silverlight를 통해 XAML을 렌더링합니다.

웹에서의 Silverlight 활용은 이제 시작 단계입니다. Silverlight는 XAML 렌더링 엔진의 유용한 기능 및 기본 웹 개발 기술의 유연한 사용을 제공하므로 개발자 도구 모음에 추가할 가치가 있는 도구입니다. 자세한 내용은 MSDN의 Silverlight 개발자 센터를 참조하십시오.

Back to top

Download Image NEW: Explore the sample code online! - or - 코드 다운로드 위치: Silverlight2007_06.exe (300KB)
Posted by -세티-
2007/12/17 10:06

안녕하세요. 세티 입니다. General .NET2007/12/17 10:06

세티의 닷넷 강좌를 쓰던 박종현 입니다.^^

네이버 블로그를 유지하다가 설치형 블로그에 잠시 머무르다가 이번에 티스토리 블로그로 완전 이사하게
되었습니다.^^

자료를 다 퍼올려고 했는데.... 너무 많아서 다 가져오지 못하겠네요.

사실 시간도 그리 많지 않구요....^^;;;

기존 세티의 닷넷 강좌는 http://blog.naver.com/nashira7 에서 확인하실 수 있습니다. ^^
Posted by -세티-
번역자: 박종현(세티)
작성일: 2007년 11월 24일

Controls Template

기본적으로 WPF의 버튼과 같은 요소들은 다른 엘리먼트들의 집합셋으로 만들어 집니다.

예를 들어서 하나의 버튼에 대해 표현을 만들어내기 위해선 기본적으로 3개의 자식 엘리먼트로 구성되어야 합니다. 하지만 컨트롤 템플릿을 사용함으로써 버튼 컨트롤과 같은 요소들이 가지는 표현을 WPF요소의 기본 표현으로 다시 되돌릴 수 있습니다.

아래는 그것에 대한 예제 입니다.

<Button Content="Not Pressed">

  <Button.Template>

    <ControlTemplate TargetType="{x:Type Button}">

      <Border x:Name="border" CornerRadius="80" Background="LightBlue">

        <ContentPresenter

Name="content"

HorizontalAlignment="Center"

VerticalAlignment="Center"

/>

      </Border>

      <ControlTemplate.Triggers>

        <Trigger Property="IsPressed" Value="True">

          <Setter TargetName="border"

 Property="Background" Value="Aqua" />

          <Setter TargetName="content"

Property="Content" Value="Pressed" />

        </Trigger>

      </ControlTemplate.Triggers>

    </ControlTemplate>

  </Button.Template>

</Button>

 

아래의 그림을 보도록 하겠습니다.

먼저 마우스를 클릭하지 않았을 때의 그림입니다.

사용자 삽입 이미지
이것을 마우스로 클릭하면 아래의 그림처럼 변합니다
사용자 삽입 이미지

Data Template

컨트롤 템플릿을 통해서 버튼의 표현 양식을 변경했듯이 데이터 템플릿을 통해서 컨트롤이 가지는 컨텐츠를 변경할 수 있습니다. 데이터 템플릿은 데이터 바운드를 비쥬얼 하게 보여주는데 자주 사용됩니다. 아래의 그림은 이미지 객체의 컬렉션이 바운드된 리스트 박스에 대한 기본 표현을 보여줍니다.

사용자 삽입 이미지

(이미지 출처: 마이크로소프트 WPF Site)


<DataTemplate x:Key="myTaskTemplate">

  <Border Name="border" BorderBrush="Aqua" BorderThickness="1"

          Padding="5" Margin="5">

    <Grid>

      <Grid.RowDefinitions>

        <RowDefinition/>

        <RowDefinition/>

        <RowDefinition/>

      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>

        <ColumnDefinition />

        <ColumnDefinition />

      </Grid.ColumnDefinitions>

      <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>

      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />

      <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>

      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>

      <TextBlock Grid.Row="2" Grid.Column="0" Text="Prioirty:"/>

      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>

    </Grid>

  </Border>

</DataTemplate>



Themes

일반적으로 WPF 어플리케이션은 다양한 UI 리소스를 가지고 있습니다. 이 리소스들은 어플리케이션을 위한 테마로 사용될 수 있습니다. WPF ResourceDictionary class 라는 캡슐화된 리소스를 사용하여 UI 패키지를 제공합니다. 테마는 다양한 어플리케이션에서 활성되고, 각각의 파일에서 리소스들을 정의할 수 있습니다.


아래는 내용에 대한 샘플 코드 입니다.

 

<!-- Blue Theme (BlueThemeResourceDictionary.xaml) -->

<ResourceDictionary

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:ThemedApplicationSample_CSharp">

    <Style TargetType="{x:Type Button}">

        <Setter Property="Background" Value="Blue" />

     </Style>

</ResourceDictionary>

 

Layout Panels

데이터를 표현하기 위한 UI를 작성할 때, 위치를 잡고, 사이즈를 조절하고, 레이아웃이 만드는데 필요한 컨트롤과 엘리먼트들을 조합해서 할 수 있습니다. WPF는 레이아웃 컨트롤을 포함하는 공통의 인프라 스트럭처를 지원하는데, 레이아웃 컨트롤은 다음과 같습니다.

Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel, WrapPanel


아래의 그림은 DockPanel을 보여줍니다.

사용자 삽입 이미지


Graphics

WPF는 다음과 같이 새로운 그래픽 특징을 포함하고 있습니다.


Resolution
device-independent 그래픽: WPF 그래픽 시스템은 Resolution device-independence 활성화를 위해 device-independent 유닛을 사용합니다. 각 디바이스는 픽셀에 대해 자유로우며 dots-per-inch로의 세팅이 자동으로 이루어집니다.

정확도의 향상: WPF coordinate 시스템은 float대신에 double을 사용합니다. 변형과 불투명도는 doubles를 사용하여 표현되어집니다. 또한 WPF는 다른 컬러 영역에서 입력된 것을 통합 지원하고 scRGB를 지원합니다.

앞선 그래픽과 애니메이션 지원: WPF는 그래픽 프로그래밍인 화면 프로세싱, 랜더링 루프 등을  단순화 했습니다.

 

하드웨어 가속기: WPF 그래픽 시스템은 CPU사용을 최소화 하고 그래픽 하드웨어 이점을 사용하기 위해 디자인되었습니다.

 

2-D 그래픽

WPF는 직사각형, 타원형과 같은 벡터드로운 2-D그래픽에 대해 공통으로 사용할 수 있는 라이브러리를 제공합니다. 또한 이것은 단지 그림을 그리는 역할만 가지지는 않습니다. 마우스나 키보드의 입력 정보를 포함하는 공통 컨트롤에서 요구되는 특징들을 가지고 있습니다.


아래는 그것에 대한 예제코드입니다.

<Window

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  x:Class="Window1" >

  <Ellipse Fill="LightBlue" MouseUp="ellipseButton_MouseUp" />

</Window>

public partial class Window1  : Window

{

    void ellipseButton_MouseUp(object sender, MouseButtonEventArgs e)

    {

        MessageBox.Show("Me, a simple ellipse, was mouse clicked!");

    }

}

사용자 삽입 이미지

WPF2-D를 그릴 때 Geometries Path를 제공합니다.

아래의 그림은 Path를 이용하여 그림을 그린 것과 브러쉬를 이용했을 때, 그리고 클립을 사용했을 때 어떻게 보이는 지를 보여줍니다.

사용자 삽입 이미지

2-D 효과

WPF 2-D로 그림을 그렸을 때 다양한 효과를 제공할 수 있도록 클래스 라이브러리가 제공됩니다. 그래디언, 비트맵, 드로잉, 비디오를 표현하는데 충분하며, 로테이션, 스케일링 등을 하는데 적합합니다.

사용자 삽입 이미지


3-D Rendering

WPF UI와 데이터를 흥미롭게 보여주기 위한 2-D 그래픽과 통합된 3-D 렌더링을 제공합니다.

사용자 삽입 이미지
 
Animation

컨트롤과 엘리먼트들을 늘어나게 하고, 흔들리게 하고 회전하게 하며, 희미해지게 하는 애니메이션을 사용하여 페이지를 재미있게 만들 수 있습니다.

사용자 삽입 이미지

Media

이미지, 비디오 그리고 오디오는 정보와 사용자 경험을 전달하는 media-rich 입니다.

 



이미지

아이콘, 배경, 애니메이션 파트 같은 부분들은 어플리케이션에서 중요한 부분입니다. 그렇기 때문에 이미지들을 자주 사용해야 할 필요가 있습니다. WPF는 이러한 것들을 다양한 방법으로 표현해 낼 수 있습니다.

사용자 삽입 이미지

(이미지 출처: 마이크로소프트 WPF Site)


비디오와 오디오

WPF의 능력 중 하나는 비디오와 오디오가 포함된 멀티미디어를 자연스럽게 지원한다는 점입니다.

<MediaElement Source="media\numbers.wmv" Width="450" Height="250" />

 


MediaElement
는 커스텀 UI의 생성을 쉽게 하고, 비디오와 오디오를 매우 유연하게 연장할 수 있습니다.

 


Document
와 프린팅

WPFfixed documents, flow documents, 그리고 XPS documents 같은 3가지 타입의 문서를 지원합니다. WPF는 생성, 보기, 관리, 프린팅을 지원하기 위한 폭넓은 서비스를 제공합니다.

 

Text 와 타이포그래피

이 파트에서의 핵심은 오픈 타입 폰트와 시스템 폰트를 쉽게 지원하는 것 입니다.

WPF는 클리어 타입의 향상과 하드웨어 가속기 때문에 텍스트 렌더링 퍼포먼스가 향상되었고

텍스트는 다른 미디어와 그래픽, 심지어 애니메이션 텍스트로 쉽게 통합될 수 있습니다.

사용자 삽입 이미지

Posted by -세티-
안녕하세요. 세티 입니다.
지난 시간에 이어 계속해서 WPF가 가지는 특징들을 알아보도록 하겠습니다.
우리는 어떤 대상을 상대하기 위해 그 대상이 가지는 특징을 파악하는데 주력할 필요가 있습니다.
개략적인 그림을 머리에 그려두면 훗날 학습하는데 더 쉽게 다가갈 수 있을테니깐요.^^

데이터바인딩

WPF 어플리케이션은 수 많은 데이터 타입과 간단한 객체들을 포함하고 있는데요~
컬렉션 객체, WPF 요소, XML Data, ADO.NET Object, 그리고 웹 서비스로와 같은 것들로 부터 반환되는 수많은 객체를 가지고 있고 우리는 그것에 대한 운영이 가능합니다. 데이터를 사용자에게 쉽게 보여주고 또한 상호작용되게 하기 위한 WPF는 하나의 메커니즘을 제공하는데요 그것은 어플리케이션 UI(User Interface)에 데이터 소스 타입을 바인드 하는 것을 말합니다.
데이터 바인딩은요~ 바인딩소스(데이터소스)와 바인딩 타겟(데이터 소비자) 사이를 싱크하는 형식적인 관계입니다.
사용자 삽입 이미지

이런 데이터바인딩은 바인딩 클래스에 의해 캡슐화됩니다.
아래의 예는 Person객체의 PersonName 프로퍼티와 TextBlock의 Text프로퍼티 간의 의존성을 보여줍니다.

<Window ... xmlns:src="clr-namespace:ApplicationNameSpace">
  ...
  <!-- Binding Source -->
  <Window.Resources>
    <src:Person x:Key="myDataSource" PersonName="Joe"/>
  </Window.Resources>
  ...
  <!-- Binding Target -->
  <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}" />
  ...
</Window>

Person객체의 PersonName 프로퍼티는 Joe라는 값을 가지고 있고, TextBlock의 Text 프로퍼티는 그것의 바인드를 서술하고 있습니다.

WPF의 데이터바인딩은 유효성, 정렬, 그룹핑 등과 같은 복합적 서비스를 제공합니다.
또한 데이터바인딩은 표준 컨트롤에 쉽게 바인드 되고, 사용자에게 보여지며, 커스터마이즈 할 수 있으며, 데이터 템플레이팅을 지원하는 인프라스트럭처를 제공합니다.

Appearance

WPF를 통해서 우리는 어플리케이션을 빌드하기 위한 컨트롤과 공통 엘리먼트 집합을 만날 수 있으며 나아가 확장, 커스터마이징, 재사용 가능한 엘리먼트와 컨트롤들 또한 만날 수 있습니다. 이것을 통해 우리는 새로운 컨트롤이나 엘리먼트를 쉽게 커스텀 컨트롤을 만들수 있습니다.
나중에 차차 더 많은 걸 배울 수 있을 겁니다.

리소스

어플리케이션내의 멀티 컨트롤은 객체의 타입과 값, 폰트, 배경, 컬러, 컨트롤 템플릿, 데이터 템플릿, 그리고 스타일을 공유합니다. WPF는 객체와 값을 define하기 위해 UI와 같이 잘 알려진 인프라스트럭처를 제공합니다.

다음의 예는 두 개의 버튼 컨트롤이 배경을 공유하는 것을 보여줍니다.

<Window
  xmlns="
http://schemas.microsoft.com/winfx/2006 ··· entation"
  xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml">
  <Window.Resources>
    <SolidColorBrush x:Key="defaultBackground" Color="Red" />
  </Window.Resources>
  < StackPanel>
    <Button Background="{StaticResource defaultBackground}">One Button</Button>
    <Label Background="{StaticResource defaultBackground}">One Label</Label>
  </StackPanel>
</Window>

리소스는 특정 컨트롤, 특정 페이지 또는 윈도우 폼 상의 모든 컨트롤이나 어플리케이션의 모든 컨트롤로 범위를 한정할 수 있습니다. 이러한 것들을 이용하여 우리는 객체나 그 값을 쉽게 재사용할 수 있습니다.

스타일

스타일은 제품을 규격화 하기 위해 사용하는 어플리케이션, 문서, UI 디자이너가 가지는 WPF에서 자주 등장하는 여러 특징들 중의 하나 입니다.
디자이너는 application-by-application에 기초해서 확장을 할 수 있습니다.
WPF는 스타일 엘리먼트 모델을 제공하며 아래의 예제는 TextBlock에 사용될 배경색을 설정하는 예제입니다.

<Style TargetType="{x:Type Button}">
  <Setter Property="Background" Value="Yellow"/>
</Style>

Posted by -세티-