블로그 이미지
* Microsoft MVP - Windows Development 2014 ~ 2019 5ring * LINE : kaki104 * facebook : https://www.facebook.com/kaki104 https://www.facebook.com/groups/w10app/ kaki104

카테고리

List All (569)
Xamarin Forms (4)
Bot Framework (19)
Azure (9)
Windows 10 (44)
WPF (3)
Facebook News & Tips (158)
Windows App(Universa.. (90)
Windows 8&8.1 (113)
Windows Phone 8 (42)
Silverlight (37)
HTML5 & MVC4 (16)
Portable Class Library (2)
Uncategorised Tips a.. (3)
Kinect for Windows (2)
ETC (12)
kaki104 Scrap (4)
App News (11)
Total530,056
Today0
Yesterday19

앞으로 윈폰 망고 버전에 대한 강좌를 올릴려고 한다. 윈도우 폰 교육 과정에서 배웠던 내용들을 기본으로 해서 나름대로 정리하고 설명을 달아서 조금씩 올릴려고 하니, 윈도우폰 엡 개발을 하는데 도움이 되었으면 한다.
우선, 필자가 받은 교육은 KOSTA의 이복영 강사님께 받은 내용임을 미리 밝혀 둔다.

 1. Microsoft.Phone.Tasks Namespace
망고가 공개된 후에 많은 기능들이 추가되었는데...그 중 몇가지 기능에 대해서 간단하게만 알아보도록 하자. 더 자세한 내용은 기본적인 사항은 Microsoft.Phone.Tasks Namespace Windows Phone September 23, 2011
http://msdn.microsoft.com/en-us/library/ff428753(v=VS.92).aspx 
이곳을 참고하면 된다.

아래 몇개의 메뉴가 더 있는데..스크롤을 해야하는 관계로 캡춰를 하지 않았다.

2. MainPage.xaml.cs

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;

namespace demo1
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Camera Capture 작업
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            CameraCaptureTask cct = new CameraCaptureTask();
            cct.Show();
            cct.Completed += new EventHandler<PhotoResult>(cct_Completed);
        }

        /// <summary>
        /// 카메라 캡춰 완료 이벤트 처리
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cct_Completed(object sender, PhotoResult e)
        {
            MessageBox.Show(e.OriginalFileName + ":" + e.ChosenPhoto.Length);
        }

        /// <summary>
        /// 핸드폰 주소록에서 이메일 주소 선택 작업
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            EmailAddressChooserTask ect = new EmailAddressChooserTask();
            ect.Completed += new EventHandler<EmailResult>(ect_Completed);
            ect.Show();
        }

        /// <summary>
        /// 이메일 주소 선택 작업 완료 이벤트 처리
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void ect_Completed(object sender, EmailResult e)
        {
            if (e.TaskResult == TaskResult.OK)
            {
                MessageBox.Show(string.Format(e.Email));
            }
        }

        /// <summary>
        /// 미디어플레이어를 이용한 음악 듣기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, RoutedEventArgs e)
        {
            MediaPlayerLauncher mpl = new MediaPlayerLauncher();
            mpl.Controls = MediaPlaybackControls.All;
            mpl.Location = MediaLocationType.Install;
            mpl.Media = new Uri("files/Kalimba.mp3", UriKind.Relative);
            mpl.Show();
        }

        /// <summary>
        /// 전화하기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, RoutedEventArgs e)
        {
            PhoneCallTask pct = new PhoneCallTask();

            pct.DisplayName = "kaki104";
            pct.PhoneNumber = "123456789"; //This is a fake number dont call :)
            pct.Show();
        }

        /// <summary>
        /// 전화번호 선택하기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, RoutedEventArgs e)
        {
            PhoneNumberChooserTask pnct = new PhoneNumberChooserTask();
            pnct.Completed += new EventHandler<PhoneNumberResult>(pnct_Completed);
            pnct.Show();
        }

        /// <summary>
        /// 전화번호 선택 완료 이벤트 처리
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void pnct_Completed(object sender, PhoneNumberResult e)
        {
            MessageBox.Show(string.Format(e.PhoneNumber));
        }

        /// <summary>
        /// 사진 선택하기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, RoutedEventArgs e)
        {
            PhotoChooserTask pct = new PhotoChooserTask();
            pct.Completed += new EventHandler<PhotoResult>(photochooser_Completed);
            pct.Show();
        }

        /// <summary>
        /// 사진 선택 완료 이벤트 처리
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void photochooser_Completed(object sender, PhotoResult e)
        {
            MessageBox.Show(string.Format("Size: " + e.ChosenPhoto.Length + " bytes"));
            MessageBox.Show(string.Format(("File Name: " + e.OriginalFileName)));
        }

        /// <summary>
        /// 검색하기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, RoutedEventArgs e)
        {
            SearchTask st = new SearchTask();
            st.SearchQuery = "silverlight";
            st.Show();
        }

        /// <summary>
        /// SMS보내기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, RoutedEventArgs e)
        {
            SmsComposeTask smsct = new SmsComposeTask();
            smsct.Show();
        }

        /// <summary>
        /// 브라우저 열기
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button9_Click(object sender, RoutedEventArgs e)
        {
            WebBrowserTask wbt = new WebBrowserTask();
            wbt.URL = "http://m.naver.com";
            wbt.Show(); 
        }
    }
}

3. 여기에 구현한 기능들은
윈도폰에서 기본으로 제공하는 것들의 사용 방법을 간단하게 본것이다. 이미 알고 있는 분들도 있겠지만.. 처음이니 찬찬히 보면 나중에 프로그램하면서 요긴하게 사용할 만한 기능들도 제법 들어있다. xaml은 첨부된 소스를 참고 하기 바란다.

다음에는 타일 오퍼레이션에 대해서 알아보도록 하겠다.

**
C:\Users\Public\Music\Sample Music\Kalimba.mp3 프로젝트에 셈플mp3파일은 윈도우에서 기본으로 제공하는 파일로서..용량관계로 삭제를 했다. 파일을 복사해서 프로젝트에 붙여 넣기 한 후 프로퍼티를..

Build Action : Content
Copy to Output Directory : Copy if newer
로 설정하면 된다.


 

'Windows Phone 8 > Samples' 카테고리의 다른 글

Self Raw Notification  (0) 2012.02.06
Deploy SQL CE 3.5 DB to Windows Phone 7.1  (1) 2012.02.05
Windows Phone 7 Isolated Storage Explorer using  (0) 2012.02.05
Tile Push Notifications Operation  (0) 2012.01.07
Tile create  (0) 2012.01.07
Basic sample  (0) 2012.01.07
Posted by MVP kaki104

년말 분위기, 진행 중이던 프로젝트도 무리 없이 진행되고 그러다보니 마음가짐이 좀 흐트러진것 같다. 그래서 다시 마음을 추스리려고, 본격적으로 서버를 구성해서 개발했던 내용이나, 여러 자료들을 호스팅 할 수 있는 서버를 구성했는데.. 그 구성 방법에 대해서 적어 보도록 하겠다.

*중요 : 꼭 이렇게 하지 않아도 된다. 닷넷깔고 실버라이트 런타임 깔고 WCF RIA Service를 각각 구해서 깔아도 된다. WCF RIA Service Tool Kit은 꼭 설치하도록 한다.

1. 가상 서버 호스팅

실버라이트 호스팅은 일반 윈도우 웹호스팅으로는 서비스를 할 수 없다. 왜냐하면.. 호스팅 업체에서.. 실버라이트 호스팅하는데 필요한 여러가지 프로그램들을 서버에 설치를 해주지 않기 때문이다. 설치해달라고 메일로 요청했더니..가상 서버 호스팅을 이용하세요~라는 답변이 왔다. 으흐흐 기존에 호스팅하고 있던 업체가 cafe24였기 때문에 그곳을 기준으로 설명하겠다. (다른 곳은 모른다)
회사에서 남는 컴퓨터가 있으면 살짝 그걸 사용하는 것도 좋은 방법일 것이다.

윈도우 가상 서버 호스팅 신청 페이지(한국기준이다)
http://www.cafe24.com/?controller=product_server_virtual&method=window

가상 서버 호스팅 신청하구 돈내구 좀 기다리면 서버 설정이 완료되었다는 메일과 문자 메시지가 온다.. 그러면 윈격데스크탑으로 나만의 가상 서버 호스팅 서버로 접속해서 프로그램을 설치하면 된다.

2. 프로그램 설치

원격데스크탑으로 접속하면 윈도우 처음 깔려있는 것과 동일하게 아무것도 없는 화면이 덩그러니 나온다.
2-1. 윈도우 업데이트 : 웬만한것은 다 한다..(정품이니까..)
2-2. 윈도우 서버용 백신프로그램을 구해서 설치한다..: 잘..
2-3. 웹플랫폼설치관리자3.0 설치 실행 : 아무래도 웹플랫폼 설치하는 데는 이넘이 재일 편하다.

http://www.microsoft.com/web/downloads/platform.aspx


영문 판을 깐것 같은데 한글로 나온다..

여기서 옵션을 클릭해서 기본 언어를 영어로..(과거에 한글과 영문 언어 차이 때문에 설치가 앙된적이 있어서..될 수 있으면 영문으로 통일을 하는 것이 좋다.)

2-4. Web Metrix 설치 : 가장 처음 설치를 한다.(여러가지 포함되어 있는 것이 많다)

2-5. Silverlight로 검색 :

2010년 4월 Silverlight 4 도구 키트 릴리스 -> 설치
이넘을 설치하면 SQL Server Express 2008 R2, Visual Web Developer 2010 Express도 함께 설치가 된다.(음..도구 키트를 깔지 앙아도 실행이 되는지는..확인을 못해봐서..개발 했을때 설치했던 프로그램을 쭈욱 깔아주었다.) 머 일단 Express는 공짜니까 깔리도록 놔둔다.

2-6. WCF RIA Service 설치

http://www.silverlight.net/learn/advanced-techniques/wcf-ria-services/get-started-with-wcf-ria-services

1.Install WCF RIA Services
•Install WCF RIA Services SP2 for Silverlight 4 and 5
•Install the WCF RIA Services Toolkit
위의 2개의 프로그램을 받아서 설치한다.


대충 설치가 끝났으면 재부팅 한번해준다.

3. IIS관리자 7.0 설정


Default Web Site -> 고급설정 -> 응용프로그램 풀->ASP.NET v4.0
여기까지 하고 실버라이트 프로젝트를 기본 사이트에 올려 놓고 실행 시키면 완료.(혹시 앙되면 리플로 남겨주기 바란다)

4. 기타 설정
4-1. 만약 기존에 만들었던 실버라이트 프로젝트에 시작 페이지 ***TestPage.aspx의 내용을 확인한다.

<param name="minRuntimeVersion" value="4.0.60310.0" />
이렇게 되어있어야 일반 컴퓨터(개발자 컴퓨터가 아닌..)에서 실행이된다.

4-2. SQL Server CE 4.0을 이용한 경우 sdf파일을 IIS_IUSERS 계정에 수정, 쓰기 권한이 있어야 열기가 가능하다.
-> 이부분은 뭔가 다른 해결책이 있을 것 같은데 아직 찾이 못함.

4-3. SQL Express Management Studio를 설치해서 SQL Express를 이용하도록한다.
-> 여기서 설치가 잘 앙될 수도 있다.


위의 내용들을 참고해서 설정하면 설치할 수 있다..(sql 서버 설정을 통해서 외부에서 접속할 수 있도록 처리해도 된다)

5. 최종 테스트
서버의 C:\inetpub\wwwroot 폴더에 실버라이트 프로젝트 중 Web 프로젝트를 복사해서 이동한다.
(전체는 필요없고 몇개의 파일들만 있으면 된다. 잘 모르면 다 복사해 놔두 된다.)
비지니스 어플리케이션으로 간단하게 만든 테스트 페이지


위의 페이지는 아무것도 업으니..대부분 뜬다.

이 페이지는 SQL CE 4.0 sdf파일을 WCF RIA Service 4.0으로 서비스하는 내용을 받아서 뿌려준것이다.

6. 사실 이렇게 설정할 때까지 여러가지 삽질을 많이 했다. 중간에 빼먹은 것이 있을 수도 있으니.
문의사항, 참고사항, 추가사항 등에 대해서 리플을 남겨주기 바란다. 앞으로 이 사이트에 게시판 프로젝트로 만들었던 내용을 이용해서 게시판을 구축할 계획이다. 또한, 이전에 개발해서 서비스 중인 몇가지 프로그램도 올려서 서비스를 할 예정이다.


 

 

 

 

 

 

 


'Uncategorised Tips and Tricks' 카테고리의 다른 글

Flow Document Overview  (0) 2014.02.04
Team Foundation Service + Git + Visual Studio  (0) 2013.06.16
Host Server Setting by Silverlight  (0) 2012.01.07
Posted by MVP kaki104

하루 빨리 마무리를 짓고 싶었는데..이제야 회원가입 부분까지 완료를 했다. 전체적으로 소스를 약간씩 수정을 해서 화면 변경부분을 수정했고, 회원 가입 처리를 위한 부분도 추가를 했는데..음..소스가 아주 마음에 꼭들지는 않는다.. 프리즘도 적용하고, RX도 적용해서 전체 적으로 싸악 다시 했으면 좋겠는데..일단 이번 게시판 프로젝은 여기까지 올리고, 당분간은 윈폰 강좌를 올리도록 하겠다.

변경된 부분에 대한 설명은 추가로 하지 않겠다. 대부분 주석을 달아 놓았으니 공부하는데 문제는 없을 것이라고 생각된다. 그리고 궁금한 사항은 리플로 남겨주기를 바란다.



ps. 게시판 프로젝트 강좌를 올리는 것은 어떻게 보면 나에게는 실험적인 것이 였는데.. 개발자들의 특성인 것 같다. 반응이 없으니..좋은지 나쁜지..다행이라고 하면 악플은 하나도 없었던 것 같다. ㅎㅎ
그래서 이 이후에 시작하는 윈폰 강좌는 엄청나게 자세하게 만들게 되었다.
Posted by MVP kaki104

이번에는 로그인 로그아웃 기능을 간단하게 구현했다. 로그인 로그아웃이 되니 이제 절반은 한것 같은 느낌이 난다. 어여 끝내고 진짜 사이트를 오픈을 빨리 해야겠다.



처음 사진은 로그인 하기 전~, 다음 사진은 로그인 하고 난 후~ 구현은 간단하게 2개의 스택패널을 만들어서 로그인 전, 로그인 후 2개를 번갈아가며 보여지도록 만들었다.

1. LoginInfo.cs
모든 뷰모델, 모델에서 임포트 시켜서 사용할 수 있도록 만들었다

using System;
using System.ComponentModel;
using System.ComponentModel.Composition;

//로그인 유저 정보
namespace SL5_BOARD.PublicData
{
    /// <summary>
    /// 로그인 정보
    /// </summary>
    [Export(typeof(LoginInfo))]
    public class LoginInfo : INotifyPropertyChanged
    {
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion

        int mstMemberIdx;
        /// <summary>
        /// 로그인 유저 idx
        /// </summary>
        public int MstMemberIdx
        {
            get
            {
                return mstMemberIdx;
            }
            set
            {
                if (mstMemberIdx != value)
                {
                    mstMemberIdx = value;
                    OnPropertyChanged("MstMemberIdx");
                }
            }
        }

        string eMail;
        /// <summary>
        /// 로그인 유저 Email
        /// </summary>
        public string EMail
        {
            get
            {
                return eMail;
            }
            set
            {
                if (eMail != value)
                {
                    eMail = value;
                    OnPropertyChanged("EMail");
                }
            }
        }

        string memberName;
        /// <summary>
        /// 로그인 유저 이름
        /// </summary>
        public string MemberName
        {
            get
            {
                return memberName;
            }
            set
            {
                if (memberName != value)
                {
                    memberName = value;
                    OnPropertyChanged("MemberName");
                }
            }
        }

        string nickName;
        /// <summary>
        /// 로그인 유저 닉네임
        /// </summary>
        public string NickName
        {
            get
            {
                return nickName;
            }
            set
            {
                if (nickName != value)
                {
                    nickName = value;
                    OnPropertyChanged("NickName");
                }
            }
        }

        DateTime lastLoginDt;
        /// <summary>
        /// 로그인 일시
        /// </summary>
        public DateTime LastLoginDt
        {
            get
            {
                return lastLoginDt;
            }
            set
            {
                if (lastLoginDt != value)
                {
                    lastLoginDt = value;
                    OnPropertyChanged("LastLoginDt");
                }
            }
        }

        string memberGrade;
        /// <summary>
        /// 로그인 유저 등급
        /// </summary>
        public string MemberGrade
        {
            get
            {
                return memberGrade;
            }
            set
            {
                if (memberGrade != value)
                {
                    memberGrade = value;
                    OnPropertyChanged("MemberGrade");
                }
            }
        }

        int listCount;
        /// <summary>
        /// 게시물 카운트
        /// </summary>
        public int ListCount
        {
            get
            {
                return listCount;
            }
            set
            {
                if (listCount != value)
                {
                    listCount = value;
                    OnPropertyChanged("ListCount");
                }
            }
        }

        int attachCount;
        /// <summary>
        /// 덧글 카운트
        /// </summary>
        public int AttachCount
        {
            get
            {
                return attachCount;
            }
            set
            {
                if (attachCount != value)
                {
                    attachCount = value;
                    OnPropertyChanged("AttachCount");
                }
            }
        }

        /// <summary>
        /// 생성자
        /// </summary>
        public LoginInfo()
        {
            InitLoginInfo();
        }

        /// <summary>
        /// 로그인 정보 초기화
        /// </summary>
        public void InitLoginInfo()
        {
            MstMemberIdx = 0;
            EMail = "";
            MemberName = "";
            LastLoginDt = DateTime.Parse("2000-01-01");
            MemberGrade = "";
            ListCount = 0;
            AttachCount = 0;
            IsLogin = false;
        }

        bool isLogin;
        /// <summary>
        /// 로그인 여부
        /// </summary>
        public bool IsLogin
        {
            get
            {
                return isLogin;
            }
            set
            {
                if (isLogin != value)
                {
                    isLogin = value;
                    OnPropertyChanged("IsLogin");
                }
            }
        }
    }
}

2. MainPageViewModel.cs

일단 방금 만든 클래스를 임포트 시켜야 한다.

        /// <summary>
        /// 로그인 정보 임포트
        /// </summary>
        [Import(typeof(LoginInfo))]
        public LoginInfo LoginIF { get; set; }


임포트를 시켰으니..이넘한테 로그인 처리된 데이터를 넣어 주어야 한다. 그럴려면 이전에 만들어 놓았던 Mst_Member 모델을 사용해야하니 그넘도 임포트를 시킨다.

        /// <summary>
        /// 로그인 처리를 하기위한 멤버마스터 모델 임포트
        /// </summary>
        MstMember mstMemberModel;
        [Import(typeof(MstMember))]
        public MstMember MstMemberModel
        {
            get
            {
                return mstMemberModel;
            }
            set
            {
                mstMemberModel = value;
                mstMemberModel.PropertyChanged += new PropertyChangedEventHandler(MstMemberModel_PropertyChanged);
            }
        }


MstMember 모델 임포트를 시키면서 프로퍼티 체인지 이벤트를 구현했다. 그래야 로그인 후에 데이터를 받아서 처리를 할 수 있기 때문이다.

        /// <summary>
        /// 멤버 마스터 모델의 프로퍼티 체인지 이벤트 구현
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MstMemberModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "MessageData":
                    //모델에서 발생한 메시지를 뷰모델로 끌어 올려서 통합 적으로 관리
                    MessageData = MstMemberModel.MessageData;
                    break;
                case "LoginMember":
                    if (MstMemberModel.LoginMember != null)
                    {
                        //로그인 성공했을 경우
                        // admin@localhost
                        // p@ssw0rd
                        MST_MEMBER member = MstMemberModel.LoginMember;

                        LoginIF.MstMemberIdx = member.MST_MEMBER_IDX;
                        LoginIF.EMail = member.EMAIL;
                        LoginIF.MemberName = member.MEMBER_NAME;
                        LoginIF.NickName = member.NICK_NAME;
                        LoginIF.MemberGrade = member.MEMBER_GRADE;

                        LoginIF.ListCount = member.BoardLists.Count;
                        LoginIF.LastLoginDt = DateTime.Now;
                        member.LAST_LOGIN_DT = DateTime.Now;
                        LoginIF.IsLogin = true;

                        //마지막 로그인 일자 저장
                        mstMemberModel.Saving();
                    }
                    else
                    {
                        //로그아웃 null값을 가지는 경우는 강제로 넣는 것 말고는 없냉
                        MessageData = "로그아웃 되었습니다.";
                        LoginEmail = "";
                        LoginPassword = "";

                        LoginIF.MstMemberIdx = 0;
                        LoginIF.EMail = "";
                        LoginIF.MemberName = "";
                        LoginIF.NickName = "";
                        LoginIF.MemberGrade = "";
                        LoginIF.ListCount = 0;
                        LoginIF.LastLoginDt = DateTime.Parse("2000-01-01");
                        LoginIF.IsLogin = false;
                    }
                    break;
            }
        }

그리고, 로그인 버튼 클릭했을 때의 로그인 커맨드와 로그아웃 커맨드 2개를 새로 만들어야한다.

        ICommand loginCommand;
        public ICommand LoginCommand
        {
            get
            {
                if (loginCommand == null)
                {
                    loginCommand = new ActionCommand(() =>
                    {
                        //로그인 확인
                        MstMemberModel.Login(LoginEmail, LoginPassword);
                    });
                }
                return loginCommand;
            }
        }

        ICommand logoutCommand;
        public ICommand LogoutCommand
        {
            get
            {
                if (logoutCommand == null)
                {
                    logoutCommand = new ActionCommand(() =>
                    {
                        //로그아웃
                        MstMemberModel.LoginMember = null;
                    });
                }
                return logoutCommand;
            }
        }

로그인 작업에서 사용한 Login() 메소드는 약간 수정이 되었다. 기존에는 loadComplete로 이동을 해서 결과를 처리 했으나, 이번에는 그냥 LoginMember에 데이터를 쑤셔 넣는 역할로 변경되었다.
(메인 페이지에 연결되어있다보니, ConditionData, CurrentData등의 기존 사용중인 것들과 같이 쓸 수가 없어서 변경했다.)

        //로그인
        public void Login(string email, string password)
        {
            //로그인시 이메일과 비밀번호를 쿼리에 넣어서 보내야함.(쿼리도 바꿔주고)
            if (BoardDomainService.Context.IsLoading == false)
            {
                BoardDomainService.Context.Load(
                                                BoardDomainService.Context.GetMstMemberByLoginQuery(email, password),
                                                LoadBehavior.RefreshCurrent,
                                                load =>
                                                {
                                                    if (load.HasError == false)
                                                    {
                                                        MessageData = "로그인 성공";
                                                        LoginMember = load.AllEntities.Cast<MST_MEMBER>().FirstOrDefault();
                                                    }
                                                },
                                                true);
            }
            else
            {
                MessageData = "조회 중이니 잠시 후 다시 시도해 주시기 바랍니다.";
            }
        }

로그아웃 커맨드에서는 LoginMember에 Null 값만 넣으면 자동으로 로그 아웃 처리가 되도록 되어있다. 음..개선의 여지는 있지만..나름 간편한 방법을 사용했다.

3. 기타 수정사항 확인

** 로그인 상태에 따른 스택패널 보이기 숨기기 작업

MainPage.xaml 을 참조

<!--로그인창-->
<Border x:Name="Login" BorderBrush="#FF81C1C7" BorderThickness="4" CornerRadius="10" Visibility="{Binding LoginIF.IsLogin, Converter={StaticResource VisibilityReversConverter}}">

.......

<!--로그인 멤버 정보 보이는 박스 영역-->
<Border x:Name="MemberInfo" BorderBrush="#FF81C1C7" BorderThickness="4" CornerRadius="10" Visibility="{Binding LoginIF.IsLogin, Converter={StaticResource VisibilityConverter}}" d:IsHidden="True">

.......

LoginIF.IsLogin 값에 따라서 보이고 앙보이게 컨버터를 이용해서 처리함

4. 전체 소스를 올리도록 하겠다.
주석이 있으니 참고하면서..소스를 보면 도움이 될 것이라고 생각한다. 소스에서 이해가 앙되거나 추가 설명이 필요한 부분은 리플로 남겨주면 다시 설명을 달도록 하겠다.

Posted by MVP kaki104

이번 강좌는 글쓰기 기능을 구현하도록 하겠다. 강좌가 너무 늦어서 잊혀져 가는 강좌였을 것인데..흐흐;; 필자도 요즘 슬럼프끼가 좀 보여서 어떻게 해야하는지 나름 고민 중인데..이번 강좌에 만은 호응을 기대해 본다.(호응 없으면...더욱더 깊은 슬럼프의 나락으로 떨어질지도..쿨럭)
이번에도 이곳 저것 수정을 해 놔서..중요한 부분은 이곳에서 설명을 하고, 나머지는 소스를 참고 할 수 있도록 소스를 올리도록 하겠다.



1. BOARD_LIST.cs

제일 시간이 오래 걸렸던 부분인데.. Code First로 텍스트 필드를 만들어 놓으면 128Byte의 기본 크기를 가지게 되는데..우리가 글을 작성할때 128바이트는 너무나 작은 사이즈라..이걸 대폭~늘려야 한다. 특히 RichTextBox를 사용해서 xaml을 직접 입출력을 할려고 하면 무지막지하게 커야한다. 그래서 클래스를 고쳤다.

[Column(TypeName="ntext")]
[MaxLength]
public string LIST_CONTENT { get; set; }
이렇게 컬럼을 수정해 놓으면 무척 만은 데이터를 저장 할 수 있게 된다.(정확한 사이즈는 MSDN에서..쿨럭)

추가로 테이블 스키마가 수정되면 전에 우리가 만들어 놓았던 SL5_BOARD_DBCONTEXTInitializer에서 데이터베이스를 Drop하고 다시 만들도록 되어 있었는데..이걸 약간 수정해보자..(데이터베이스 드롭되면 기존 데이터 다 날라가니..아무래도 좀..)

public class SL5_BOARD_DBCONTEXTInitializer
        : CreateDatabaseIfNotExists<SL5_BOARD_DBCONTEXT>

이렇게 변경해 놓으면 데이터베이스 파일이 존재 하지 않을 때만 새로 만들어 준다.

에..그럼 기존 데이터베이스를 보존할려면 수동으로 스키마를 수정해야하는데..Server Explorer를 열어서 SL5_BOARD.sdf 파일을 연결 하고 Tables을 열어서 BOARD_LIST를 오른쪽 마우스로 클릭하면 Edit Table Schema를 선택하고, LIST_CONTEXT의 Data Type을 ntext로 변경하고 OK를 눌러주면 된다.



위의 그림을 참고해서 수정한다.

2. 글쓰기 버튼 클릭~

BoardListViewModel.cs 일부 소스

ICommand addCommand;
/// <summary>
/// 추가 커맨드
/// </summary>
public ICommand AddCommand
{
    get
    {
        if (addCommand == null)
        {
            addCommand = new ActionCommand(() =>
            {
                BOARD_LIST obj = new BOARD_LIST();
                obj.BOARD_MAIN_IDX = BoardMain.CurrentData.BOARD_MAIN_IDX;

                //요기 1은 나중에 로그인 기능이 추가되면 로그인 유저 아이디로 변경
                obj.MST_MEMBER_IDX = 1;
                BoardListData.Adding(obj);

                //수정 상태로 바로 변경

                IsEditting = true;
            });
        }
        return addCommand;
    }
}

BoardList.cs 일부소스

/// <summary>
/// 추가 함수
/// </summary>
/// <param name="addData">BOARD_LIST</param>
public void Adding(Object addData)
{
    if (addData != null && addData is BOARD_LIST)
    {
        BOARD_LIST item = addData as BOARD_LIST;

        //요기 등록일시 넣는 부분과 등록자 아이디 넣는 부분 차후에 위치 변경 예정
        item.REG_DT = DateTime.Now;
        item.REG_IDX = 1;

        //컨텍스트에 넣궁

        BoardDomainService.Context.BOARD_LISTs.Add(item);

        //컨디션데이터에도 넣구
        ConditionData.Add(item);

        //현재 데이터에 넣는다 -> 이렇게 넣으면 화면 변경되는 거 알죠?
        CurrentData = item;

        MessageData = "추가 작업을 완료 했습니다.";
    }
    else
    {
        MessageData = "데이터가 없거나 형식이 다릅니다.";
    }
}


3. 저장 버튼 클릭

리치텍스트 박스의 xaml 프로퍼티는 직접 바인딩을 해보니 오류가 난다;; 그래서 시간 관계상 패수~ ㅋ

ICommand saveCommand;
/// <summary>
/// 저장 커맨드
/// </summary>
public ICommand SaveCommand
{
    get
    {
        if (saveCommand == null)
        {
            saveCommand = new ActionCommand(item =>
            {
                RichTextBox rtb = item as RichTextBox;
                if (rtb != null)
                {

                    //현재 데이터에 LIST_CONTEXT에 리치텍스트박스 xaml프로퍼티 값을 바로 넣음
                    BoardListData.CurrentData.LIST_CONTENT = rtb.Xaml;

                    //그리고 저장
                    BoardListData.Saving();
                }

                //편집상태는 false로
                IsEditting = false;
            });
        }
        return saveCommand;
    }
}


BoardList.cs 일부

/// <summary>
/// 저장 함수
/// </summary>
public void Saving()
{

    //나중에 여기도 좀 바꿔야 하는뎅..에..이번에는 그냥 평범하게..
    BoardDomainService.Context.SubmitChanges(submitCallBack, null);
}

요기는 특별히 할일은 없음

4. 조회 시
뷰모델에 있는 BoardListData의 프로퍼티 체인지 이벤트를 이용해서 CurrentData가 변경되면 그 데이터를 리치텍스트박스에 넣도록 코딩함.

BoardListDetailView.xaml.cs 일부

[Import(typeof(BoardListViewModel))]
public BoardListViewModel BoardListVM
{
    get
    {
        return this.DataContext as BoardListViewModel;
    }
    set
    {
        this.DataContext = value;
        value.BoardListData.PropertyChanged += new PropertyChangedEventHandler(BoardListData_PropertyChanged);
    }
}

void BoardListData_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "CurrentData":
            if (BoardListVM.BoardListData.CurrentData != null)
            {
                if (BoardListVM.BoardListData.CurrentData.LIST_CONTENT != null)
                    rtb.Xaml = BoardListVM.BoardListData.CurrentData.LIST_CONTENT;
                else
                    rtb.Blocks.Clear();
            }
            break;
    }
}

5. 프로그램이 좀 심플하고 깔끔하게 나오면 좋은데..^^;;; ..
당분간 한번 쭈욱~ 만들어서..한번에 쾅~하고 올려야 될 것 같다. 중간 중간 과정을 보여주기 위해서 여러번 나누어서 올리고 있는데.. 진도가 너무 앙나간다;; 지금 처럼 단계별로 올리는 것이 좋은 분들은 리플 남겨 주시면 현재 상태를 유지하고..무플인 경우에는 한번에 왕창 올리도록 하겠다. 으흐흐..왕창~~~~~~~~~~~~~

ps.첨부한 소스는 실버라이트 소스만 있습니다. 서버 소스는 포함되어 있지 않습니다. 참고하세요

Posted by MVP kaki104