NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# 자동 완성 기능을 포함하는 TextBox 만들기.

    페이지 정보

    본문

    안녕하세요. 소심비형입니다. 오늘은 자동 완성 기능이 있는 TextBox를 만들어 보도록 하겠습니다. 더불어, 가져온 데이타를 바인딩할 때 병렬 처리와 실시간 데이타 바인딩 처리도 같이 알아보겠습니다. 뭔가 내용이 거창하죠^^? 마음에 여유를 가지고 천천히 따라하다보면 자동 완성기능에 대한 메커니즘을 이해할 수 있을겁니다. 시작이 반이죠~

     

    시작...

    NG.Tools 프로젝트에 TextBoxControl폴더와 클래스를 하나 추가합니다.

    yuWbZqW.png

     

     

    이 컨트롤의 Concept은 텍스트 컨트롤에 포커스가 들어올 때 실시간으로 바인딩 데이타를 가져오는 방식입니다. 물론, UsedRealTimeDataBinding의 속성이 True로 설정되어 있어야합니다. 이 속성을 잘 못 사용하면 성능에 문제가 발생할 수도 있기 때문에 별도로 사용 여부에 대한 속성을 두었습니다.

    /// <summary>       
    /// 연결된 데이타 소스를 기반으로 자동 완성 기능 사용 여부를 설정하거나 가져옵니다.        
    /// </summary>        
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), 
        Category("NGMasterExtension"), 
        DefaultValue(false), 
        Browsable(true), 
        NG.Controls.Component.Description("AutoCompleteMessage")]
    public bool UsedAutoComplete
    {
        get
        {
            return this.usedAutoComplete;
        }
        set
        {
            this.usedAutoComplete = value;
     
            if (this.usedAutoComplete)
            {
                collection = new AutoCompleteStringCollection();
                this.MaskBox.AutoCompleteMode = AutoCompleteMode;
                this.MaskBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
                if (usedRealTimeDataBinding)
                {
                    this.GotFocus -= new System.EventHandler(AutoCompleteTextBoxControl_GotFocus);
                    this.GotFocus += new System.EventHandler(AutoCompleteTextBoxControl_GotFocus);
                }
            }
            else
            {
                collection = null;
                this.MaskBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None;
                this.MaskBox.AutoCompleteSource = AutoCompleteSource.None;
                this.GotFocus -= new System.EventHandler(AutoCompleteTextBoxControl_GotFocus);
            }
        }
    }
    

     

     

    아래 코드와 같이 Xml Documentation을 입력하면 Doxygen에서 샘플 코드를 출력할 수 있습니다. 이 메소드는 사용자로부터 데이타를 받는 속성입니다. 이 속성으로 처리할 수 있는 형식은 IDataSource와 IQuery를 상속 받은 Collection입니다.

    /// <summary>        
    /// 자동 완성 기능에 데이타를 표시하기 위한 데이타 소스를 가져오거나 설정합니다.       
    /// <para>이 데이타는 기본적으로 중복이 제거된(Distinct) 상태로 바인딩됩니다.</para>       
    /// </summary>       
    /// <remarks>     
    /// <example>       
    /// 이 샘플은 <see cref="AutoCompleteDataSource"/>속성을 설정하거나 가져오는 방법을 보여줍니다.      
    /// <code>        
    /// // EntityFramework의 ObjectContext를 생성합니다.    
    /// APP.EntityFramework.YourEntities entities = new EntityFramework.YourEntities();    
    /// 
    /// // 자동 완성 기능을 사용함으로 변경합니다.        
    /// this.autoCompleteTextBoxControl1.UsedAutoComplete = true;       
    /// 
    /// // 페이지가 로드될 때 이 컨트롤도 데이타를 바인딩한 상태로 로드하려면, 이 값을 false로 지정하세요.    
    /// // 이렇게하면 이 컨트롤의 최초 응답 속도가 향상됩니다.        
    /// // 주의: 페이지의 로딩 속도가 저하될 수 있습니다.       
    /// this.autoCompleteTextBoxControl1.IsLazyBindingMode = false;       
    /// 
    /// // 실시간 데이타를 바인딩합니다.        
    /// // 실시간으로 데이타를 검색할 필요가 없으면 이 값을 false로 설정하세요.        
    /// this.autoCompleteTextBoxControl1.UsedRealTimeDataSource = true;        
    /// 
    /// // 자동 완성 기능이 동작해야 하는 방법을 설정합니다.      
    /// // 기본값은 None입니다.        
    /// this.autoCompleteTextBoxControl1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;      
    /// 
    /// // 클라이언트에서 바인딩 될 때 병렬처리를 지원합니다.        
    /// // 데이타량이 작은 경우는 병렬 처리를 해도 효과가 없을 수 있습니다.        
    /// // 이 의미는 데이타베이스에서 쿼리하는 속도와는 무관합니다. 이미 클라이언트로 데이타를 가져온 후 컨트롤에 바인딩 할 때 병렬 처리를 지원합니다.        
    /// this.autoCompleteTextBoxControl1.IsParallel = true;        
    /// 
    /// // 늦은 바인딩이 적용되는 IEnumerable 또는 IListSource로 케스팅이 될 수 있는 데이타 타입입니다.       
    /// this.autoCompleteTextBoxControl1.AutoCompleteDataSource = entities.YourDataSource.Select(item => item.Name);        
    /// </code>      
    /// </example>     
    /// </remarks>        
    [AttributeProvider(typeof(IListSource))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
    Category("NGMasterExtension"),
    DefaultValue(null),
    Browsable(true),
    NG.Controls.Component.Description("AutoCompleteDataSourceMessage")]
    public object AutoCompleteDataSource
    {
        get { return this.autoCompleteDataSource; }
        set
        {
            this.autoCompleteDataSource = value as IListSource;
            if (!isLazyBindingMode)
                DataBind();
        }
    }

     

     

    위에서 Xml Documentation의 Code는 Doxygen에서 아래와 같이 표시됩니다. 좀 더 실용적인 Documentation을 만들려면 부지런해야 하기도 하고, 정확하게 이해하고 작성해야 하겠습니다. 그리고 정말 도움이 되려면 이렇게 예제를 가능한한 많이 제공하는게 좋습니다^^;

    KNEsV9w.jpg

     

     

    DevExpress의 TextEdit에는 AutoComplete를 지원하는 기능이 포함되어 있습니다. 이 기능을 활성화 해야 자동 완성 기능을 구현할 수 있기에 아래 91라인처럼, 초기화 메소드에서 처리해야 합니다.

    /// <summary>        
    /// 컨트롤을 다른 컨테이너에 추가한 후 호출됩니다.      
    /// </summary>        
    protected override void InitLayout()
    {
        base.InitLayout();
        this.MaskBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.None;
        this.isLazyBindingMode = true;
    }

     

     

    이제 Data를 처리하는 메소드를 추가합니다. 224라인에서 IsParallel 속성에 따라 병렬 처리 및 단일 처리를 하게끔 분기되어 있습니다. 패러럴 프로그래밍과 패러다임에 대해서는 별도로 자세하게 알아봐야 할거 같습니다. 이 예제만 하더라도 양이 방대한데다 실제로 성능에 향상이 있는지까지 검증해야 하기에 여기서 이야기하기에는 무리입니다. 여러분들도 아시겠지만, 무조건 병렬 처리를 한다고 해서 성능에 향상이 있는것은 아닙니다. 그렇기에 사용 여부를 선택할 수 있도록 속성을 추가해 두었습니다. 실제로 1개의 Column과 10,000개의 Row가 있는 DataTable인 경우 단일 처리가 약 2배 가까이 빠릅니다. 이렇듯, 상황에 따라 차이가 크고, 어떻게 병렬 처리를 구현하는가에 따라서 또 달라집니다.

    /// <summary>      
    /// 데이타를 바인딩합니다.  
    /// </summary>        
    private void DataBind()
    {
        if (this.autoCompleteDataSource != null)
        {
            collection.Clear();
            IList collections = (this.autoCompleteDataSource as IListSource).GetList();
            string[] list = IsParallel ? GetDataSetToArrayByParallel(collections) : GetDataSetToArrayBySingle(collections);
            collection.AddRange(list);
            this.MaskBox.AutoCompleteCustomSource = collection;
        }
    }

     

     

    이제 View에 TextBoxControl을 올려 놓고 아래와 같이 코딩한 후 실행해 봅시다.

    protected override void OnLoad(EventArgs e)
    {
        _presenter.OnViewReady();
        base.OnLoad(e);
        // 자동 완성 기능을 사용함으로 변경합니다.            
        this.textBoxControl1.UsedAutoComplete = true;
        // 페이지가 로드될 때 이 컨트롤도 데이타를 바인딩한 상태로 로드하려면, 이 값을 false로 지정하세요.            
        // 이렇게하면 이 컨트롤의 최초 응답 속도가 향상됩니다.            
        // 주의: 페이지의 로딩 속도가 저하될 수 있습니다.            
        this.textBoxControl1.IsLazyBindingMode = false;
        // 실시간 데이타를 바인딩합니다.            
        // 실시간으로 데이타를 검색할 필요가 없으면 이 값을 false로 설정하세요.            
        this.textBoxControl1.UsedRealTimeDataBinding = false;
        // 자동 완성 기능이 동작해야 하는 방법을 설정합니다.            
        // 기본값은 None입니다.            
        this.textBoxControl1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        // 클라이언트에서 바인딩 될 때 병렬처리를 지원합니다.            
        // 데이타량이 작은 경우는 병렬 처리를 해도 효과가 없을 수 있습니다.            
        // 이 의미는 데이타베이스에서 쿼리하는 속도와는 무관합니다. 이미 클라이언트로 데이타를 가져온 후 컨트롤에 바인딩 할 때 병렬 처리를 지원합니다.            
        this.textBoxControl1.IsParallel = false;
        // 늦은 바인딩이 적용되는 IEnumerable 또는 IListSource로 케스팅이 될 수 있는 데이타 타입입니다.            
        this.textBoxControl1.AutoCompleteDataSource = Services.DataService.GetDataTable();
    }

     

     

    실행한 후 확인해 보면 자동 완성 기능이 잘 동작하는지 알 수 있습니다. TextBoxControl에서 "t"를 입력하면 자동으로 찾아주고, 추가까지 해줍니다. (옵션에서 SuggestAppend를 선택 했으므로...) DB에서 데이타를 변경하면서 테스트도 해보시면 RealTime으로 변경되는 것도 확인할 수 있습니다.

    OFKDF1J.png

     

     

    위에 보면 이전에 했던 Natural sorting도 적용할 수 있습니다. 지금은 적용되어 있지 않지만, 아주 간단하게 처리가 가능합니다. 이로써 자동 완성 기능을 포함하는 TextBoxControl을 만들어 보았습니다. 다음에는 SharpGL (OpenGL)을 이용하여 반도체에서 사용되는 Wafer의 Vector와 Color map에 대해서 알아 보겠습니다.

     

    다음 시간에...

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.