정말 오랜만의 포스팅입니다. (이제부터 예의바른 블로거가 되기위해 존댓말로 포스팅하기로 했습니다)
핑계없는 무덤은 없다지만 핑계를 대자면,, 지금 진행하는 프로젝트에 쫒겨 시간이 없었다고,,라고 하고싶지만
게을러서 입니다. 게으른 블로거되서는 안되는데 큰일입니다;;

아무튼 이번 포스트에서는 FindName(); 메서드에 대해 알아보려 합니다.
여러분은 Silverlight App를 개발하면서 FindName()을 사용하십니까?
사실 일찌감치 FindName() 메서드의 존재와 역할을 알았지만 필요없는 메소드라 생각하여 잊어버렸습니다.
사용하지 않았죠...;

FindName();
System.Windows.Documents 네임스페이스의 Inline 클래스의 멤버매서드
역  할 : 개체의 x:Name 또는 Name 특성 값을 참조하여 Silverlight 개체를 가져온다.
인자값 : string
리턴형 : object


Page에 Rectangle이 있고 x:Name이 MyRect라고 할때  Page.xaml.cs에서는 MyRect라는 x:Name만으로도
Rectangle객체의 컨트롤이 가능합니다.
 예를들어 이런것이죠  >>   this.MyRect.Width = 100;
x:Name만 알아도 충분히 컨트롤이 가능한데 굳이 아래와 같이 복잡하게 객체를 알아올 필요성을 못느낀것이죠.
object o = this.FindName("MyRect");
Rectangle myrect = o as Rectangle;
if (myrect != null)
{
     // to do..
 }


그럼 FindName을 어떤때 써야될까요? 저는 이런 경우에 활용해 보았습니다.
를들어 보자면 로그인하는 시나리오가 적당하겠네요.

Page에서 로그인 버튼을 누르면 로그인 컨트롤(UserControl로 만들어진)이 새로 뜨고 사용자는 ID와 PW를 입력하여 로그인 하게 됩니다. 로그인 된다면 Page의 TextBlock에 사용자가 입력한 ID가 나타나게 한다고 합시다.

Page는 로그인 컨트롤을 알고 있지만(로그인 컨트롤의 Public한 속성에 접근할수 있지만) 로그인 컨트롤은
Page를 알지 못합니다. 물론 로그인컨트롤의 비하인드코드에서 this.parent를 이용하여 부모는 알수있을 겁니다.
하지만 (Page)this.parent;처럼 Page클래스로 캐스팅하면 컴파일 타임에 오류를 일으킵니다. 캐스팅 할수가 없죠.

저는 이걸 해결하기 위해 로그인 컨트롤의 생성자를 오버로딩하여 Page의 TextBlock 컨트롤을 인자로 넘겨주는 방법으로 코딩해왔습니다.

하지만 FindName을 이용하여 해결 할 수도 있습니다. this.parent를 찾아서 Panel로 캐스팅후
FindName() 메서드를 호출하여 TextBlock 개체를 찾으면 되는것이죠!
굳이 생성자에 넘기고 자시고 할 필요가 없습니다.

자.. 방법을 알았으니 간단한 스텁 프로그램을 작성해 보도록 하겠습니다.(앞에서 말한 로그인 예제로 하죠)

1. 우선 실버라이트 응용프로그램을 생성하구요 (프로젝트명을 FindNameTesting으로 했습니다.)
2. Page.xaml블랜드에서 열어 디자인 합니다. 간단하게 TextBlock(x:Name = "txtUserID")
   버튼(x:Name = "btnLog")을 하나 넣었습니다.
   버튼은 Grid로 만들었구요.. Grid안에 Rectangle 객체와 TextBlock(x:Name = "txtLogMSG")를 넣었습니다.


2. Silverlight 사용자정의 컨트롤(UserControl)을 추가 합니다.(LogInControl이라 명명 했습니다.)
    LogInControl을 블랜드에서 열어 디자인해 줍니다. 저는 아래와 같이 했구요;

  그냥 간단하게 ID를 입력받는 TextBox(x:Name = "txtInputID") 와  PW를 입력받는 PasswordBox(x:Name = "txtInputPW")를 추가하고 버튼(x:Name = "btnLogIn")도 하나 놓습니다.

3. 이제 LogInControl의 비하인드 코드(LogInControl.xaml.cs)로 가서 이벤트 처리 메서드를 작성합니다.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace FindNameTesting
{
    public partial class LogInControl : UserControl
    {
        public LogInControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(LogInControl_Loaded);
        }

        void LogInControl_Loaded(object sender, RoutedEventArgs e)
        {
            btnLogIn.MouseLeftButtonDown += new MouseButtonEventHandler(btnLogIn_MouseLeftButtonDown);
        }

        void btnLogIn_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!CheckedIdAndPw())            
            {
                Storyboard1.Begin();
                return;
            }
            object o = ((Panel)this.Parent).FindName("txtUserID");
            TextBlock txtuserid = o as TextBlock;
            if (txtuserid != null)
            {
                txtuserid.Text = string.Format("{0}님 환영합니다^^",txtInputID.Text);
            }

            object o2 = ((Panel)this.Parent).FindName("txtLogMSG");
            TextBlock txtlogmsg = o2 as TextBlock;
            if (txtlogmsg != null)
            {
                txtlogmsg.Text = "LogOut";
            }
            ((Panel)this.Parent).Children.Remove(this);            
        }

        private bool CheckedIdAndPw()
        {
            if (txtInputID.Text != "맨날맑음" || txtInputPW.Password != "silverlight")
            {
                return false;
            }
            return true;
        }
    }
}

    로그인 버튼을 누르면 LoginControl의 부모인 Page에서 txtUserID개체를 찾아 입력받은 ID를 대입했구요
    같은방법으로 Page에 있는 로그버튼의 TextBlock을 찾아 LogIn이라는 글자도 LogOut으로 변경하였습니다.
    그후에 생성된 LoginControl을 Page에서 제거 하였습니다.

4. 마지막으로 Page.xaml.cs를 작성합니다.
using System.Windows.Controls;
using System.Windows.Input;

namespace FindNameTesting
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            this.btnLog.MouseLeftButtonDown += new MouseButtonEventHandler(btnLog_MouseLeftButtonDown);
        }

        void btnLog_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (txtLogMSG.Text == "LogIn")
            {
                this.LayoutRoot.Children.Add(new LogInControl());
            }
            else
            {
                txtLogMSG.Text = "LogIn";
                txtUserID.Text = "안녕하세요? 로그인하세요";
            }
        }
    }
}

매우 간단합니다. 버튼을 누르게 되면 로그인컨트롤(LogINControl)을 생성합니다자..이제 로그인하게되면
로그인한 화면이 Page의 TextBox를 갱신시킬까요?... 네~잘됩니다
아래는 지금 만든 예제를 조금 수정한 것입니다~(ID : 맨날맑음, PW : silverlight) 테스트 해보시면 잘되는걸 볼 수있습니다.



이외에도 WPF에서는 FindName() 메서드로 개체를 불러와야만 개체의 컨트롤이 가능합니다~
이 방법을 사용하면 부모든 부모의 부모든 상관없이 type만 알고있다면 모든 컨트롤을 제어할수 있겠고,
public한 속성들도 제어할 수 있습니다!
다른 쓰임새가 많겠지만 아직 실력이 미천하여 이럴때 사용하고 있습니다;
다른곳에 활용하신분들은 피드백이나 댓글 부탁드립니다.
Posted by 맨날맑음