시나리오

DB에서 어떠한 값들을 가져오는데

가져올때 COUNT에 맞춰서 컨트롤을 증가시켜서 새로운 창을 띄운다.


Crop_Temper();  //쿼리에서 값 가져오기
ColumnDefine(); //열 생성
RowDefine();    //로우 생성
AddLine();      //동적으로 컨트롤 생성
ButtonAdd();    //버튼생성



1.
Crop_Temper() 에서 어떠한 컨트롤 생성할때 필요한 값들을 가져온다. 여기에서 가져온 COUNT만큼 Row의

갯수를 증가시킬것이다.


2.
        private void ColumnDefine() //열을 증가시킨다.
        {          
            ColumnDefinition column1 = new ColumnDefinition();
            column1.MinWidth = 100;
            ColumnDefinition column2 = new ColumnDefinition();
            column2.MinWidth = 150;

            MainGrid.ColumnDefinitions.Add(column1);
            MainGrid.ColumnDefinitions.Add(column2);

        }

3.
        private void RowDefine() //행을 추가한다.
        {
            for (int i = 0; i <= Temper_List.Temper_Name.Count; i++)  //DB에서 가져온 값갯수만큼 행을 만든다.
            {
                RowDefinition row1 = new RowDefinition();
                row1.MinHeight = 30;                               
                MainGrid.RowDefinitions.Add(row1);               
            }           
        }

4.
        private void AddLine() //입력창 추가
        {
            for (int i = 0; i < Temper_List.Temper_Name.Count; i++) 
            {       
//여기서는 행과 열에 맞게 라벨과 텍스트박스를 추가시킨다.

                Label lbTest1 = new Label();
                lbTest1.Content = Temper_List.Temper_Name[i].ToString();
                lbTest1.FontSize = 12;
                lbTest1.HorizontalAlignment = HorizontalAlignment.Center;
                lbTest1.VerticalAlignment = VerticalAlignment.Center;   

                Grid.SetRow(lbTest1, i);
                Grid.SetColumn(lbTest1, 0);
                MainGrid.Children.Add(lbTest1);

                TextBox tbTest1 = new TextBox();
                tbTest1.TextAlignment = TextAlignment.Center;
                tbTest1.VerticalContentAlignment = VerticalAlignment.Center;
                Grid.SetRow(tbTest1, i);
                Grid.SetColumn(tbTest1, 1);
               MainGrid.Children.Add(tbTest1);
            }           
        }

5. 버튼도 위와 같은 식으로 추가한다.



위와같이 했다면 아래와 같이 창이 뜨게 될것이다.
DB에서 가져오는 값들이 다름에 따라 창들도 동적으로 변한다.


Posted by 아몰라

댓글을 달아 주세요



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


WPF 구성요소를 클릭한다.




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



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



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;
                
    }
}   


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}"

 

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

 

 

 

Posted by 아몰라

댓글을 달아 주세요

  1. 2016.01.26 19:50 신고

    저도 똑같이 미디어플레이어에 클럭 넣었더니 컨트롤이 안되다가 방법을 찾았는데 해결하실 것 같아서 댓글 남겨봅니다.

    미디어 플레이어에 ScrubbingEnabled=True 참으로 허용해주시고, mediaElement.Clock.Controller.Seek(TimeSpan.FromMilliseconds(M_milliseconds), TimeSeekOrigin.BeginTime) 로 position을 변경할 수 있습니다.

    http://stackoverflow.com/questions/2993733/creating-a-simple-seeking-media-player-with-mediaelement-in-wpf


http://cafe.naver.com/uxbakery.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=109
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 아몰라

댓글을 달아 주세요

이전버튼 1 이전버튼