등록
                                                                           실행

이번 프로젝트는 WPF에서 영상을 띄우고 사용자가 그 영상에서 특정한 시간대에 자기가 넣고싶은 데이터를 등록하고 그것을 영상을 실행시켰을 때 등록한 데이터들이 영상 옆에 뜨는것이다.


옆에 텍스트창은 리치텍스트박스로 만들어져있고 5줄마다 한페이지로 기록되게해놓았다.
저장을하게되면 페이지마다 시작시간과 종료시간을 적고 저장을 하게된다.



영상을 실행을 하게되면 등록한 데이터들이 오른쪽 Flow Document에 뜨게된다.




우선..프로젝트를 진행하였지만 결론부터 말하면 실패다. 구현할려고 하였던 기능을 시간안에 구현하지 못하였다.
시간이 있으면 더 구현하였겠지만 지금 하고있는 최종 프로젝트가 끝나게 되거나 시간이 남을 시에 나머지를 다 구현해야겠다.

영상옆에 자막을 띄우는 정도밖에 못하였다.


다음에 추가적으로 구현해야 될 부분은

1. 이미지 추가
2. 영상 추가(해당영상 옆에 보조로 보여줄수있는 영상)
3. 텍스트 폰트 효과(Flow Document에 적용해야 한다.)
4. XML파일과 동영상파일 매핑시키기
5. 자막처리 알고리즘 보완
Posted by 아몰라


마우스 우클릭 후 항목선택을 한다.


WPF 구성요소를 클릭한다.




가져올 사용자정의컨트롤을 클릭한다.



도구상자에 컨트롤이 들어와있다. 이제 가져다쓰면된다~



'.NET > WPF' 카테고리의 다른 글

동적으로 컨트롤 생성하기  (0) 2010.07.21
미디어플레이어 (동기화해결)  (0) 2010.04.22
WPF에서 미디어 플레이어 만들기  (1) 2010.04.19
사용자지정과 사용자정의 컨트롤 차이  (0) 2010.04.18
의존속성  (0) 2010.04.16
Posted by 아몰라

           
             리스트뷰에 먼저 헤더를 삽입한다.
            처음에 "" 이렇게 빈 헤더를 넣었는데 이유는 모르겠으나 subitem을 넣을때 
            자꾸 첫번재 열 다음부터 값이들어가서 임의대로 ""로 해놓고 길이도 1로해놨다.
            이상하게 2번째 열부터 값이들어간다.

            listView1.Columns.Add("", 1, HorizontalAlignment.Left);
            listView1.Columns.Add("싱크시작", 100, HorizontalAlignment.Left);
            listView1.Columns.Add("싱크종료", 100, HorizontalAlignment.Left);
            listView1.Columns.Add("자막내용", 200, HorizontalAlignment.Left);

            listView1.View = View.Details;

            listView1.FullRowSelect = true;
            listView1.GridLines = true;


다음에 실제 값들을 넣는다.
            ListViewItem item;

            item.SubItems.Add(temp);
           
            item.SubItems.Add(temp2);

            item.SubItems.Add(temp3);                
                   
            listView1.Items.AddRange(new ListViewItem[] { item});

이렇게 값이들어간다.




마지막으로 값을 가져오고싶을때는 아래와같이 가져 올수 있다.

string name = listView1.Items[0].SubItems[1].Text;


'.NET > C#' 카테고리의 다른 글

윈도우 서비스 만들기  (0) 2010.04.04
ReadLine, Read, ReadKey  (0) 2010.04.03
어셈블리 동적 로딩  (0) 2010.03.31
Const Vs Readonly  (0) 2010.03.29
Sealed  (0) 2010.03.29
Posted by 아몰라


우선 전에 썼었던 MediaTimeline과 MediaClock 클래스를 사용하지않았다.

Timeline을 셋팅하고 그 상태서 Clock을 생성하고 그 Clock을 MediaElement와 연결했지만

연결을 하게되면 MediaElement로 제어가 되질않고  미디어엘리먼트의 클락의 컨트롤러로 제어를 해야됐다. 그리고  MediaElement에 position을 지정 해줄수 가 없었다. position을 임의로 지정하게 되면

미디어를 지정하는동안 클락을 변경할 수 없다 라는 오류가 난다.

이것을 해결하기위해서 여러 방법을 써봤는데 해결하지 못하였고

결국 MediaTImeline과 MediaClock을 사용하지 않는 방법을 사용하였다.

해결방법은

DispatcherTimer를 이용하였는데  우선 bool 변수를 하나 선언해서

매초마다 이벤트가 발생해서 미디어 -> 슬라이더바가  변경 될때와

슬라이더바가 움직여서 영상이 바뀔때가 겹치지않게 bool로 제어를 해주었다.


아래와같다~!

bool con = false;

//마우스를 떼면 false로 바뀌고 Tick이 다시 계속 실행된다.
private void timebar_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
      con = false;            
}        

//마우스를 클릭하면 true로 바뀌고
private void timebar_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
      con = true;
}

//클릭하면서 true로 바뀌었고  Tick이 발생안한다. 그 때 바를 움직여서 Position을 바꿔놓는다.
private void timebar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
       if (con)
      {
       int SliderValue = (int)timebar.Value;

       TimeSpan ts = new TimeSpan(0, 0, 0, 0, SliderValue);

       mediaElement1.Position = ts;
       }
}

//초기값이 false이기 때문에 계속 실행된다.
void timer_Tick(object sender, EventArgs e)
{
    if (!con)
    {
        timebar.Value = mediaElement1.Position.TotalMilliseconds;   
              
        TimeSpan ts = new TimeSpan();
        ts = mediaElement1.Position;
                
        textBox1.Text = (string)ts.Seconds;
                
    }
}   


'.NET > WPF' 카테고리의 다른 글

동적으로 컨트롤 생성하기  (0) 2010.07.21
WPF에서 사용자정의컨트롤 쓰기  (0) 2010.04.26
WPF에서 미디어 플레이어 만들기  (1) 2010.04.19
사용자지정과 사용자정의 컨트롤 차이  (0) 2010.04.18
의존속성  (0) 2010.04.16
Posted by 아몰라


네이버 OPEN API 나 DAUM OPEN API나 키 발급받는것은 비슷하기 때문에 올리지 않겠다.

키 발급받을대 주의 사항은 URL을 적는게 있는데 키 발급받은걸 사용하려면 키 발급받을때 적은 URL과 똑같이 만들어서 사용하던가 아니면 해당 URL의 하위폴더로해서 만들면 된다.



네이버


<Script type="text/javascript"
src="http://map.naver.com/js/naverMap.naver?key=발급받은 키">
</script>
 
</head>
<body>

<div id='mapBox' style='width:600px;height:600px'></div> //맵 사이즈 지정
   
<script type ="text/javascript">

    //****************************** Map 생성 ******************************
    var map = new NMap(document.getElementById('mapBox'));
    map.setCenterAndZoom(new NPoint(321198, 529730), 3);

    //****************************** NZoomControl 생성 ******************************
    var zoom = new NZoomControl();
    zoom.setAlign("left");    // 슬라이드바의 좌우 설정
    zoom.setValign("top");  // 슬라이드바의 위,아래 설정
    map.addControl(zoom);
    map.addControl(new NIndexMap());  // 미니맵 생성


    //****************************** 이벤트 리스너******************************
    var regFlag = false;

    function addClick() {  //맵이라는 객체에서 클릭이라는 이벤트가 발생하면 clicked라는 함수를 호출한다.

           NEvent.addListener(map, "click", clicked);
            regFlag = true;
        }
    }

    function removeClick() {   //등록된 이벤트리스너를 해제시킨다.
  NEvent.removeListener(map, "click", clicked);
        regFlag = false;
    }

    function clicked(pos) {
        alert("이곳의 좌표 : " + pos);
    }


    //****************************** 마크생성 ******************************
    var cnt = 0;
    NEvent.addListener(map, "click", clickMap);

    function clickMap(pos) {
        if (cnt >= 20) {
            alert('마커는 20개까지만 추가 가능합니다.');
            return;
        }

        cnt++;
        map.addOverlay(createMarker(pos, cnt, "마커" + cnt));
    }
   
    function createMarker(pos, count, content) {
        var iconUrl = "http://cfs.tistory.com/blog/plugins/tatterDesk/image/ico_tag.gif";
        var marker = new NMark(pos, new NIcon(iconUrl, new NSize(15, 14)));

        NEvent.addListener(marker, "mouseover", function(pos) { //마우스가 마커객체있을시에 정보를보여준다.
      infowin.set(pos,
            "<TABLE style='width:80px;height:50px;border:solid 1px #666666'><TR><TD>" + content + "  "+ pos + "</TD></TR></TABLE>"); infowin.showWindow()
        });

        NEvent.addListener(marker, "mouseout", function() { infowin.hideWindow(); });
//마우스가 나가면 정보를 안보여준다.
return marker;
    }     
   

    var infowin = new NInfoWindow();
    map.addOverlay(infowin);

   

</script>
    
    <button onclick='map.zoomIn()'>+</button>
    <button onclick='map.setZoom(1)'>1</button>
    <button onclick='map.setZoom(3)'>2</button>
    <button onclick='map.setZoom(5)'>3</button>
    <button onclick='map.setZoom(7)'>4</button>
    <button onclick='map.zoomOut()'>-</button>
   
<button onclick=addClick()>click event 실행</button><button onclick=removeClick()>click event 제거</button>
</body>
</html>



DAUM



<Script type="text/javascript" src="http://apis.daum.net/maps/maps2.js?apikey=발급받은 키script>
</head>
<body>

<div id="map" style="width:600px;height:400px;"></div> 
   
<script type ="text/javascript">      
   
    var cnt;
    //맵 생성
    var map = new DMap("map");
    map.setCenter(new DLatLng(37.529196714213114, 126.92506196011036), 2);
   
   
    //주요 컨트롤 셋팅
    var indexMapControl = new DIndexMapControl();
    var zoomControl = new DZoomControl();
    var mapTypeControl = new DMapTypeControl()
   
    map.addControl(indexMapControl);
    map.addControl(zoomControl);
    map.addControl(mapTypeControl);
   
    indexMapControl.setAlign("left");
    zoomControl.setVAlign("middle");
   
  
   //이벤트리스너 등록
   DEvent.addListener(map, "click", clickMap);
  
   //이벤트발생
   function clickMap(pos) {
        if (cnt >= 20) {
            alert('마커는 20개까지만 추가 가능합니다.');
            return;
        }

        cnt++;
        map.addOverlay(createMarker(pos));
    }
 
    //마커생성
    function createMarker(pos) {
       
        var marker = new DMark(pos);                    
       
        return marker;
   }

</script>
    
 
</body>
</html>


결론은 네이버나 DAUM이나 사용하는 함수나 방법은 거의 똑같다. 단 DAUM은 로드맵이나 더 많은 클래스들과 기능들을 제공해주는 거같다. 개인적으로 DAUM을 더 추천한다.

위에 예제는 그냥 API를 갔다 붙여서 쓰는정도 밖에 안되서 적절한 예제는 아니지만

활용방법 하나 예를 들자면 DB에 어느 특정 지역에대한 정보를 입력해놓고 맵을 마우스로 클릭했을때 마커를 등록시켜 해당 마커의 정보와 DB에 있는 데이터와 비교해서 찍은곳이 같은 곳일시에 DB에 그 해당 지역에 대한 정보들을 등록해놨던것을 보여주는 활용방법이 있겠다.

원래는 실현해볼려고했는데 자바스크립트도 잘모르겠고 뭔가 모르게 잘 안되서...나중에 꼭 다시 해서 API 활용법을 올리도록하겠다!~




Posted by 아몰라

주요 클래스

 

 

MediaElement – 오디오 및 비디오를 컨트롤 할 수 있게 해주는 클래스

 

- 미디어를 대화형으로 중지, 일시 중지 및 재생할 수 있으려면 MediaElementLoadedBehavior속성을 Manual로 설정해야 합니다

 

 

 

MediaTimeline - MediaTimeline은 해당 영상 Timeline 개체에서 영상을 제어하는 것과 같은 방식으로 미디어 타이밍에 대한 제어를 제공하는 개체

 

- MediaTimeline에는 연결된 Duration BeginTime 속성이 있으며 이 속성을 사용하여 미디어의 시작 시간재생 시간을 지정할 수 있다.

 

 

 

MediaClock - 미디어의 타이밍 상태를 유지 관리한다.

 

 

 

 

클래스간의 연동

 

 

- MediaTimeline 개체에서 생성된 Clock개체를 생성해서 MediaClock으로 값을 대입해주고 MediaClock MediaElement와 연결 시켜준다.

 

)

1. MediaClock  mc =  MediaTimeline.CreateClock();

 

2. mediaelement.Clock = mc;

 

당연히 위에 타임라인에서 클락을 생성할 때 타임라인에는 기본적인 정보들이 들어가 있어야 한다.

 

 

 

 

 

미디어플레이어만들기

 

 

1.     미디어가 정보들이 셋팅되어서 열릴 준비가 되었을 때

 

타임슬라이더바에 전체시간 적용

private void mediaElement1_MediaOpened(object sender, RoutedEventArgs e)

        {           

            timebar.Maximum = mediaElement1.NaturalDuration.TimeSpan.TotalMilliseconds;

}

 

 

 

2.     미디어를 열 때

 

파일을 열고 클락과 엘리먼트를 연동시켜준 후 이벤트를 등록한다.

private void open_Click(object sender, RoutedEventArgs e)

        {           

            ofd = new OpenFileDialog(); 

            ofd.Filter = "Media file (*.*)|*.*"; //파일 필터링

           

            ofd.ShowDialog();  //다이얼로그 박스 띄우기

            try

            {

                volume_slider.Value = 0.5;

                Uri uri = new Uri(ofd.FileName); //선택한 파일 데이터타입 uri로 형변환

                                        

                volume_slider.Value = mediaElement1.Volume * 10;

 

                timeline.Source = uri;

                TimeSpan tp = new TimeSpan(0, 0, 0);

                timeline.BeginTime = tp;

                timeline.Duration = mediaElement1.NaturalDuration;

               

                mc = timeline.CreateClock();                               

                mediaElement1.Clock = mc;

               

                mc.CurrentTimeInvalidated += new EventHandler(_CurrentTimeInvaildated);

               //미디어 타임이벤트 등록

            }

            catch { }

        }

 

 

 

 

 

 

3.     미디어타임 이벤트 발생시

 

시간변경시 타임슬라이더바 값 변경

private void _CurrentTimeInvaildated(object sender, EventArgs e)

        {

           timebar.Value = mediaElement1.Position.TotalMilliseconds;                                

        }

 

 

 

4.     타임슬라이더 위치 수동으로 변화시

 

마우스 끌어서 슬라이더바 특정시간으로 옮기기

private void timebar_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)

        {           

           int SliderValue = (int)timebar.Value;                           

 

           TimeSpan ts = new TimeSpan(0, 0, 0, 0, SliderValue);

 

           try

           {

               mediaElement1.Position = ts;    //위치변화              

           }

           catch { }

 

           mediaElement1.Clock.Controller.Resume();          

        }       

       

        

        private void timebar_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

        {

            mediaElement1.Clock.Controller.Pause();

        }

사실 위와같이 하면 포지션의 위치가 바껴야되는게 맞지만 클락과 엘리먼트가 연동되있는 상태에서는 이것이 안되는걸 발견하였다.

 

이러한 오류가발생한다.

미디어 플레이어에 클럭이 지정되는 동안 이 작업을 수행할 수 없습니다

그래서 이것을 해결하기위해 미디어를 정지시켜놓고도 해보고  클락을 해제했다가도 해보고 여러가지 방법을 써봤지만 해결을 못하였다.

 

결론은 일단은 클락을 연동안시키고 해결하는 방법밖에 없다. 그러면 슬라이더바만을 특정시간으로 이동시킬수 있다.

 

방법이 있겠지만 아직 해결못하여서 해결되게되면 업데이트 하겠다.

5.     재생, 정지, 잠시멈춤, 다시재생

 

 


private void button1_Click(object sender, RoutedEventArgs e)

        {

            mediaElement1.Clock.Controller.Begin();           

        }

 

        private void stop_Click(object sender, RoutedEventArgs e)

        {

            mediaElement1.Clock.Controller.Stop();

           

            timebar.Value = 0;

           

        }

 

        private void pause_Click(object sender, RoutedEventArgs e)

        {

            mediaElement1.Clock.Controller.Pause();

        }

 

        private void pause_r_Click(object sender, RoutedEventArgs e)

        {

            mediaElement1.Clock.Controller.Resume();

        }

 

 

 

TIP – 위에서는 타임슬라이더 연동하는것만 나왔는데 볼륨슬라이더도 있다. 볼륨슬라이더는 아주 쉬운 방법으로 영상과 연동시켰다.

 

XAML 코드에 바인딩만 추가 하면 된다.

 

Value="{Binding ElementName=mediaElement1 , Path=Position, Mode=TwoWay}"

 

 
시간이 되면 못다한 기능들을 더 추가해야겠다!~!
 

 

 

 

'.NET > WPF' 카테고리의 다른 글

동적으로 컨트롤 생성하기  (0) 2010.07.21
WPF에서 사용자정의컨트롤 쓰기  (0) 2010.04.26
미디어플레이어 (동기화해결)  (0) 2010.04.22
사용자지정과 사용자정의 컨트롤 차이  (0) 2010.04.18
의존속성  (0) 2010.04.16
Posted by 아몰라

'.NET > WPF' 카테고리의 다른 글

동적으로 컨트롤 생성하기  (0) 2010.07.21
WPF에서 사용자정의컨트롤 쓰기  (0) 2010.04.26
미디어플레이어 (동기화해결)  (0) 2010.04.22
WPF에서 미디어 플레이어 만들기  (1) 2010.04.19
의존속성  (0) 2010.04.16
Posted by 아몰라
2010. 4. 16. 19:23
의존속성은 일반적인 프로퍼티와 같은 방식으로 사용되도록 설계되었기 때문에 눈치 채지 못했을 수도 있다.
의존속성은 일반적인 프로퍼티가 아니다. 전통적인 .NET 유형으로 정의된 일반적인 프로퍼티에 WPF기능이 추가된 것이라고 생각하자. (일반적인 프로퍼티 + WPF 기능)


                          이렇게 구성됨으로써 WPF는 .NET 세계의 안정성을 붕괴시키지 않고서도
                          프로퍼티 같은 기본적인 구성 요소를 변경 할 수 있게 된다.

순서

1. 의존속성 정의
2. 의존속성 등록



1.의존속성 정의

FrameworkElement 클래스는 Margin 프로퍼티를 정의하는데, 이 프로퍼티는 모든 요소들이 공유한다. Margin 프로퍼티는 의존속성이다. 즉, Margin 프로퍼티는 FrameworkElement 클래스에 다음과 같이 정의되어 있다.

public calss FrameworkElement : UIElement, ...
{
     public static readonly DependencyProperty MarginProperty;  //의존속성 정의
     ...
}

- 의존속성을 정의하는 필드는 일반적인 프로퍼티 이름에 위와 같이 Property라는 단어를 추가하는 형태를 갖는다.
- 의존속성 필드는 readonly 필드로 정의된다. 이는 의존 속성 필드는 오직 FrameworkElement 클래스의 static 생성자에서만 설정될 수 있다는 것을 의미한다.

2.의존속성 등록

-
DependencyProperty 클래스에는 public 생성자가 없기 때문에 DependencyProperty 클래스의 인스턴스가 직접적으로 생성될 수 없다. (static dencyProperty.Register()메서드만을 사용해서 생성)

- DependencyProperty멤버들이 읽기 전용 이기 때문에 개체가 생성된 이후에 값을 변경 할 수 없기 때문에 DependencyProperty 멤버의 값은 반드시 Register()메서드의 인자로 제공되어야 한다.


예제)
DependencyProperty 개체를 생성하는 방법을 보여준다. FrameworkElement 클래스는 static 생성자를 사용하여 MarginProperty 필드를 초기화한다.


static FreamworkElement()
{
     FreamworkPropertyMetadata metadata = new FrameworkPropertymetadata(
     new Thickness(), FreameworkPropertyMetadataOptions.AffectsMeasure);

     FrameworkPropertyMetadata 개체를 생성하는 단계이다. 이 개체는 의존속성에서 사용하고 싶은 서비스를 나타낸다. 데이터바인딩이나 애니매이션, 저널링(journaling)을 지원하는 것과 같은 서비스가 해당된다.



     MarginProperty = DependencyProperty.Register("Margin",
     typeof(Thickness), typeof(FrameworkElement), metadata,
     new ValidataValueCallback(FrameworkElement.IsMarginValid));
     ...

     static DependencyProperty.Register()메서드를 호출하여 의존속성을 등록하는 단계이다.



Register 메서드의 Parameta
- 프로퍼티 이름, 여기서는 Margin이 된다.
- 프로퍼티가 사용할 데이터 타입, 이 예제에서는 Thickness 구조체가 된다.
- 이 프로퍼티를 소유하게 될 타입, 이 예제에서는 FrameworkElement 클래스가 된다.
- 선택적으로, 추가적인 프로퍼티 설정을 갖고 있는 FrameworkPropertyMetadata 개체.
- 선택적으로, 프로퍼티의 유효성 검사를 수행하는 콜백.


}


프로퍼티 유효성 검사

유효성 검사 콜백(validation callback)은  반드시 object 타입의 매개변수를 받아들이고, Boolean 타입의 값을 반환하는 메서드를 가리켜야 한다. 개체가 유효하다고 받아들이면 true값을 반환하고, 개체를 거부하려면 false값을 반환하면 된다.


예) FrameworkElement.Margin 프로퍼티의 유효성검사

FrameworkElement.IsMarginValid()메서드는 internal Thickness.IsValid()메서드에 의존하는데 Thickness.IsValid()메서드는 Thickness  개체가 마진을 표현하는 현재 용도로 유효한지를 확인한다.

private static bool IsMarginValid(object value)
{
     Thickness thickness1 = (Thickness) value;
     return thickness1.isValid(true, false, true, false);
}

제한사항 -  이 콜백은 static 메서드를 가리켜야 하며 유효성 검사가 수행되는 개체에는 접근할 수 없어야 한다는 것이다. 유효성 검사 콜백 메서드에서 얻을 수 있는 전부는 유효성 검사가 적용되는 의존 속성에 새롭게 적용되는 값뿐이다. 이러한 점은 유효성 검사 콜백을 쉽게 재사용하도록 해 주지만, 다른 프로퍼티를 고려하는 유효성 검사 루틴을 만들 수 없도록 해준다.


----------------------------------------------------미완------------------------------------------------

Posted by 아몰라


Page - 웹 응용 프로그램을 위한 프로그래밍 가능한 사용자 인터페이스


- 브라우저 또는 클라이언트 장치를 통해 사용자에게 정보를 표시하며 서버 측 코드를 사용하여 응용 프로그램 논리를 구현

- 스타일, 레이아웃 등의 기능에 해당 브라우저 호환 HTML을 자동으로 렌더링함.

- 웹 페이지의 구성요소는 시각적 구성 요소와 논리라는 두 부분으로 나뉨









Response , Request 참고 - http://cafe.naver.com/79nana.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=642

'.NET > ASP.NET' 카테고리의 다른 글

Cookie, View State, Hidden Field, IsPostBack 란?  (0) 2010.04.08
Posted by 아몰라
개요

페이지가 서버에 게시될 때마다 웹 페이지 클래스의 새 인스턴스가 만들어진다.
일반적인 웹 프로그래밍에서 이러한 작업을 수행하면 라운드트립 시 페이지와 해당 페이지에 있는 컨트롤과 관련된 정보가 손실된다.

예를 들어, 사용자가 텍스트 상자에 정보를 입력하면 그 정보는 브라우저 또는 클라이언트 장치에서 서버로 보내는 라운드트립에서 손실된다.

데이터를 유지할 수 있는 옵션들 - Cookie, View State, Hidden Field, IsPostBack




IsPostBack - Page개체의 중요한 속성이다. 현재 페이지가 처음 Load되었는지, PostBack된 상태인지를 구별하는 속성이다.

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            ViewState["LOAD_TIME"] = DateTime.Now;
        }
    }






Hidden Field 

서버에 게시할 때 유지되어야 하는 값을 저장하는 데 사용됩니다. 이 컨트롤은 <input type= "hidden"/> 요소로 렌더링됩니다.   (렌더링 - 사용자가 직접 눈으로 볼 수 있게 이미지화 하는거)

대개 뷰 상태, 세션 상태 및 쿠키가 Web Forms 페이지의 상태를 유지하는 데 사용됩니다. 그러나 이러한 방법을 사용하지 않도록 설정했거나 사용할 수 없는 경우에는 HiddenField 컨트롤을 사용하여 상태 값을 저장할 수 있습니다.

HiddenField 컨트롤의 값을 지정하려면 Value 속성을 사용합니다. ValueChanged 이벤트에 대한 이벤트 처리기를 만들어 서버에 대한 게시 사이에 HiddenField 컨트롤의 값이 변경될 때마다 호출되는 루틴을 제공할 수 있습니다.






ViewState

웹에서는 상태를 유지하기위한 여러가지 방법들을 사용합니다.

그 예로는 Application, Session, Cookie, ViewState 등등.. 이외에도 여러가지 방법들이 있습니다.

(김영욱님의 하기1, 하기2 를 참고하시기 바랍니다.)

 

이중에서 ViewState만 다루어보도록 하겠습니다. 이후 다른 상태유지에 대해서는 직접 알아보는 재미를 느껴보시기 바랍니다.^^

 

ViewState에 대해 언급하는 이유는 VisualStudio(이하 VS)에서 사용하는 서버 컨트롤 들은 기본적으로 상태유지를 위해 ViewState를 사용합니다.

 

사용자가 따로 설정하지 않아도 자체적으로 ViewState에 상태값을 저장해두었다가 불러 사용합니다. 이내용은 지난 시간의 이지 실행주기의 내용에 언급되어 있으니 참고하시면 좋을 듯 합니다.

컨트롤 속성에는 ViewSate를 사용하지 않는 옵션(EnableViewState)도 있으니 참고하시기 바랍니다.

 

상태유지란 의미를 모르시는 분들을 위해 간단하게 설명해드리겠습니다.

 

웹페이지는 기본적으로 HTML형식의 문서입니다.

입력을 위한 input태그 빼고는 대부분의 태그들은 표현을 위한 태그들이 대다수 입니다.

Input 태그 또한 새로고침등의 자기 자신을 다시 호출하는 경우에는 input 태그의 text타입에 있던 내용들도 사라지게 됩니다.

 

예제 1 )

<input id="Text1" type="text" />

<input id="Button1" type="button" value="button" />

 input 태그를 이용한 textbox“dnc”를 입력

 

새로 고침(F5)


 textbox에 “dnc”란 글자가 사라짐

 

그러나 서버 컨트롤은 앞에서 언급한 바와 같이 ViewState를 이용한 상태유지를 합니다.

서버컨트롤을 이용해서 예제 1과 같은 예제를 만들어 보겠습니다.

 

예제 2 )

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Button" />

 

 서버컨트롤 textbox“dnc”를 입력

 새로 고침(F5)

 textbox에 “dnc”란 글자가 사라짐


 
어라? 서버 컨트롤을 사용해도 다른 변화는 없습니다.

이게 어떻게 된 일일까요? 분명 앞에서는 서버컨트롤은 자체적으로 ViewState를 이용해서 상태유지를 한다고 말했었는데 거짓말을 한 것 일까요?

 

상태유지를 하지 못한 이유는 이전 포스팅의 페이지 실행 주기를 참고하시기 바랍니다.

페이지 실행 주기를 보게 되면 ViewState 복구와 저장을 하는 시점이 있습니다.

ViewState에 저장을 하기위해서는 실행주기를 거쳐야 한다는 말이 되겠죠?

그말은 서버에 갔다와야 한다. PostBack이 발생해야 한다는 말이 되겠습니다.

 

이번에는 예제 2 와 같지만 버튼을 한번눌러 PostBack을 일으켜 서버에 갔다온이후 새로고침을 해보겠습니다.

 

예제 3 )

 서버컨트롤 textbox“dnc”를 입력

 Button을 클릭 (페이지 실행주기가 실행)

 새로 고침(F5)

 textbox에 “dnc”란 글자가 존재함

 

그럼 html 컨트롤들은 Server 컨트롤들처럼 자체적으로 상태유지를 할 수 없는 것인가??

꼭 그렇진 않습니다. Html 컨트롤에 runat="server" 속성을 넣어주면 서버컨트롤처럼 사용할 수 있습니다.

 

지금까지는 컨트롤에서 ViewState를 사용하는 부분에 대해 이야기를 해보았습니다.

이번에는 사용자가 직접 ViewState를 사용하는 이야기를 해보도록 하죠^^

사용은 아주 간단합니다.

 

예제 4 )

// ViewState에 상태값 설정

ViewState["상태유지"] = "상태값";

// ViewState에서 상태값을 가져옴

string str상태유지 = (string)ViewState["상태유지"];

 

예제 4와 같은 형태로 ViewState에 데이터를 설정 및 가져올 수 있습니다.

하지만 보시는 것처럼 Boxing, UnBoxing이 발생하는걸 볼 수 있습니다.

Boxing, UnBoxing이 발생한다는 말은 부하가 심해진다는 말이죠

많이 사용하면 좋지 않다는 말입니다.

 

그리고 ViewState같은 경우 페이지에 input태그의 hidden 형태로 존재하기 때문에 서버와의 통신시 많은량의 데이터 전송이 발생하게 됩니다.

 

예제 5 )

페이지의 소스보기를 하면 다음과 같은 소스를 볼 수 있습니다.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMjY4MTkwNDYwZGQINdZC2Y34uVAOpUIXzxBu3ijnGA==" />

ViewState의 값들이 Base64()을 통해 인코딩을 해서 hidden형태로 관리하는걸 볼 수 있습니다.

페이지에 노출이 되기 때문에 보안에 아주 취약합니다. Base64로 인코딩을 하였어도 얼마든지 디코딩을 할 수 있기 때문입니다. 그리고 Base64로 인코딩을 하면서 기존의 값들보다 많은 문자열이 발생하는걸 볼 수 있습니다. ViewState를 많이 사용하면 할수록 서버와의 통신시 많은 데이터를 주고 받아야하는 부하를 가지게 됩니다.




예제

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            ViewState["LOAD_TIME"] = DateTime.Now;
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
       
        if (ViewState["LOAD_TIME"] != null)
        {
            this.Label1.Text = "로드시간:"
                + Convert.ToDateTime(ViewState["LOAD_TIME"]).ToShortTimeString();
        }
    }







실행 후 리스트박스의 항목을 선택 후 새로 고침을 해도 그 상태 그대로 유지 된다! 그 이유는

VIEWSTATE 항목은 웹 페이지에 대한 현재 상태 정보를 저장하는 곳이다.  페이지를 다시 읽어오는 경우에도 정상적으로 리스트 컨트롤의 선택 정보를 표시 할 수 있도록 VIEWSTATE 항목에 저장했다가 보여 주는 것이다.




Cookie - 일반적으로 쿠키는 웹 응용 프로그램에서 연속성을 유지 관리하는 방법, 즉 상태 관리를 수행 하는 방법 중 하나이다. 사용자가 여러 사이트를 방문할 경우 각 사이트에서는 사용자의 브라우저에 쿠키를 보내고 브라우저에서는 모든 쿠키를 개별적으로 저장한다.


장점

- 만료 시기 구성 규칙 (만들어진원인은 기본적으로 서버에서 클라이언트의 파일을 삭제할 수 없기 때문이다.)
쿠키는 브라우저 세션이 종료될 때 만료될 수도 있고 클라이언트의 만료 규칙에 따라 클라이언트 컴퓨터에 무기한 보관될 수도 있다.

- 서버 리소스 불필요
쿠키는 클라이언트에 저장되며 게시된 후 서버에서 읽는다.

- 단순성
쿠키는 단순한 키 값으로 구성된 간단한 텍스트 기반 구조다.

- 데이터 지속성
클라이언트의 쿠키 만료 프로세스 및 사용자 개입에 따라 클라이언트 컴퓨터의 쿠키 보존 기간이 결정되지만 일반적으로 쿠키는 클라이언트에 보관되는 데이터 중 가장 오래 보관된다.


단점

- 크기 제한

대부분의 브라우저에서는 쿠키 크기를 4096바이트로 제한하고 있다.

- 사용자에 의한 쿠키 거부

일부 사용자는 브라우저나 클라이언트 장치에서 쿠키 수신 기능을 사용하지 않으므로 이 기능이 제한됩니다.

- 잠재적 보안 위험

쿠키는 손상될 가능성이 높습니다. 사용자가 컴퓨터에서 쿠키를 조작할 수 있기 때문에 잠재적으로 보안 위험을 일으키거나 쿠키를 사용하는 응용 프로그램에 오류가 발생할 수 있습니다.


예제

protected void Page_Load(object sender, EventArgs e)
    {
        StringBuilder sb = new StringBuilder();

        HttpCookie cookie = Request.Cookies.Get("DateCookie"); //이러한 쿠키가 있나 확인 없으면 null
       
        //자동 로그인 = 쿠키
        if (cookie == null)
        {
            sb.Append("클라이언트에서 쿠키를받지않음");
            sb.Append("생성한 쿠키를 response에 추가");

            cookie = new HttpCookie("DateCookie");

            cookie.Value = DateTime.Now.ToString();

            cookie.Expires = DateTime.Now.AddMinutes(10);     //해당 파일이 언제까지 유효한지 설정
                                                                                                    //유효 시간이 지나면 파괴
           
            Response.Cookies.Add(cookie);
        }

        else
        {
            sb.Append("클라이언트에서 쿠키를 검색<br/>");
            sb.Append("Cookie Name: " +cookie.Name + "<br/>" );
            sb.Append("Cookie Value: " + cookie.Value + "<br/>");
            sb.Append("Cookie 만료날짜" + cookie.Expires.ToString() + "<br/>");
        }

        Label1.Text = sb.ToString();

    }


ViewState 출처 - http://dncblog.tistory.com/47   

'.NET > ASP.NET' 카테고리의 다른 글

Page (Request, Response)  (0) 2010.04.08
Posted by 아몰라
이전버튼 1 2 이전버튼