WPF 툴킷을 이용하면 자동완성을 구현 할 수 있다.

근데 이게 중간단어 검색도 안되고 좀 불편해서 지랄맞다 ㅜ_ㅜ

http://kojaedoo.tistory.com/607

 

 

 

 

그래서  걍 만드는게 속편함

일단 허접하게 만들어서 사용하자

(항상 얘기하지만 이 코드는 최적화가 안되었슴다.)

 

우선 UI 부터 보고 얘기

 

중간단어 검색도 사용가능! 키보드로 위아래 이동가능!

개체도 받아올수 있다!

물론 개체이름이 중복이 아닐때 ㅜㅜ

아래는 개체를 통해서 9살이라는 걸 받아옴

코드시작

바인딩되는 Person.cs 개체

이코드를 자동완성 아이템  소스로 사용할꺼다

WindowAutoComplate.xaml UI

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfRibbonApplication1" xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="d" x:Class="WpfRibbonApplication1.WindowAutoComplate"
        Title="WindowAutoComplate" 
        Height="339" Width="575" 
        xmlns:my1="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon">
    
    <Window.Resources>    
    </Window.Resources>
    <Grid>
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FFB2B2B2" Offset="0"/>
                <GradientStop Color="#FF5C5C5C" Offset="1"/>
            </LinearGradientBrush>
        </Grid.Background>
        <local:CustomAutoComplateBox Margin="51,95,208,172" x:Name="CustomAuto" Text="" />
        <Label Content="자동완성" Height="28" HorizontalAlignment="Left" Margin="51,61,0,0" Name="label1" VerticalAlignment="Top" Foreground="White" />
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="270,134,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="51,134,0,0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="133" />
    </Grid>
</Window>

 

 

WindowAutoComplate.xaml.cs

    /// <summary>
    /// WindowAutoComplate.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class WindowAutoComplate : Window
    {
        public WindowAutoComplate()
        {
            InitializeComponent();

            List<Person> list = new List<Person>();

            //데이터바인딩할 개체
            for (int i = 0; i < 10; i++)
            {
                list.Add(new Person() { Name = "kojaedoo" + i.ToString(), Age = i });
            }
            for (int i = 0; i < 10; i++)
            {
                list.Add(new Person() { Name = "고재두" + i.ToString(), Age = i });
            }            

            //리스트박스에 표시될 이름
            this.CustomAuto.DisplayMemberPath = "Name";
            this.CustomAuto.DataSource = list;            
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if( this.CustomAuto.SelectedItem != null){
                this.textBlock1.Text = "이사람의 나이는"+((Person)this.CustomAuto.SelectedItem).Age.ToString();
            }
        }
    }

 

 

CustomAutoComplateBox.CS 소스코드

아래에 보면 AutoComplateBindingData 클래스가 하나 더 있습니다. 여기서 어떤객체가 들어올지 모르기 때문에 여기서

이렇게 담아두고 DisplayMemberPath 넘겨줘서 ToString 할때 DisplayMemberPath  이름의 프로퍼티를 찾습니다.

 

아래는 외부에서 바인딩 할때 사용법입니다. 그럼 자동완성에는 Name이 표시된다.. Age를입력하면 리스트박스에 Age가 출력되며 Age 자동완성이 돌아간다.

 

 

여기서 부터 코드 시작

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Collections;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Reflection;
using System.Windows.Input;
namespace WpfRibbonApplication1
{

    public class CustomAutoComplateBox : Grid
    {
        private Popup __Popup = new Popup();
        private ListBox __ListBox = new ListBox();
        private TextBox __TextBox = new TextBox();

        /// <summary>
        /// 셀렉트박스에서 사용자가 선택하고 있는 상태를 관리한다.
        /// </summary>
        private bool __IsUserSelected = false;

        private List<AutoComplateBindingData> __AutoComplateBindingDataSourceList = new List<AutoComplateBindingData>();
        public CustomAutoComplateBox()
        {
            __TextBox.Text = "자동완성 텍스트 박스";

            __Popup.Name = "AutoPop";
            //_ListBox.Background = Brushes.Red;
            __ListBox.BorderBrush = Brushes.Orange;
            __ListBox.Background = Brushes.Orange;
            __ListBox.Foreground = Brushes.White;

            __Popup.Child = __ListBox;

            this.Children.Add(__TextBox);
            this.Children.Add(__Popup);

            __TextBox.TextChanged += new TextChangedEventHandler(tb_TextChanged);
            __TextBox.LostFocus += new RoutedEventHandler(tb_LostFocus);

            __TextBox.PreviewKeyUp += new System.Windows.Input.KeyEventHandler(__TextBox_PreviewKeyUp);
            __ListBox.SelectionChanged += new SelectionChangedEventHandler(__ListBox_SelectionChanged);
           

        }



        void __TextBox_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            var uie = e.OriginalSource as UIElement;

            if (e.Key == Key.Down)
            {
                e.Handled = true;

                MoveToListCursor(1);
            }

            if (e.Key == Key.Up)
            {
                e.Handled = true;
                MoveToListCursor(-1);
            }

            if (e.Key == Key.Enter)
            {
                e.Handled = true;
                if (this.__ListBox.SelectedItem != null)
                {
                    this.__TextBox.Text = this.__ListBox.SelectedItem.ToString();
                    this.__TextBox.Select(__TextBox.Text.Length, 0);

                }
                CloseListBox();
            }
        }


        /// <summary>
        /// 테스트박스에서 사용자가 한칸내림 한칸올림 사용할수 있게 처리
        /// </summary>
        /// <param name="p"></param>
        private void MoveToListCursor(int p)
        {
            int moveIndex = this.__ListBox.SelectedIndex + p;

            if (moveIndex <= -1 || this.__ListBox.Items.Count <= 0) //행이없음 내려가거나 올라갈 이유가 없음
            {
                if (this.__Popup.IsOpen)
                {
                    __IsUserSelected = false;
                    CloseListBox();
                    return;
                }
            }
            if (moveIndex > -1 && moveIndex <= this.__ListBox.Items.Count)
            {
                __IsUserSelected = true;
                this.__ListBox.SelectedIndex = moveIndex;
                OpenListBox();
            }

        }

        void __ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (((ListBox)sender).SelectedItem != null)
            {
                string result = ((ListBox)sender).SelectedItem.ToString();
                if (__IsUserSelected == false)
                {
                    this.__TextBox.Text = result;
                    this.__TextBox.Select(__TextBox.Text.Length, 0);
                }
            }
        }

        void tb_LostFocus(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            CloseListBox();
        }

        void tb_TextChanged(object sender, TextChangedEventArgs e)
        {
            e.Handled = true;
            FindText();
        }

        private void FindText()
        {
            this.__ListBox.ItemsSource = null;
            if (!string.IsNullOrWhiteSpace(this.__TextBox.Text))
            {
                var query = from c in __AutoComplateBindingDataSourceList
                            where c.ToString().Contains(this.__TextBox.Text)
                            select c;
                this.__ListBox.ItemsSource = query;

                OpenListBox();
            }
            else
            {
                CloseListBox();
            }

        }

        private void OpenListBox()
        {
            this.__Popup.Visibility = System.Windows.Visibility.Visible;
            if (this.__ListBox.Items.Count <= 0)
            {
                this.__ListBox.Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                this.__ListBox.Visibility = System.Windows.Visibility.Visible;
            }

            this.__Popup.IsOpen = true;
        }

        private void CloseListBox()
        {
            if (this.__ListBox.Items.Count > 0)
            {
                this.__ListBox.SelectedIndex = -1;
            }
            this.__Popup.Visibility = System.Windows.Visibility.Collapsed;
            this.__Popup.IsOpen = false;
        }

        private IEnumerable _DataSource;
        /// <summary>
        /// 자동완성에서 검색할 데이터소스
        /// </summary>
        public IEnumerable DataSource
        {
            get { return _DataSource; }
            set
            {
                _DataSource = value;
                __BindListBox(value);
            }

        }

        private void __BindListBox(IEnumerable values)
        {
            foreach (var value in values)
            {
                this.__AutoComplateBindingDataSourceList.Add(new AutoComplateBindingData(value as Object, DisplayMemberPath));
            }
        }

        private string _DisplayMemberPath;
        /// <summary>
        /// 바인딩하기 전에 먼저 설정
        /// </summary>
        public string DisplayMemberPath
        {
            get
            {
                return _DisplayMemberPath;
            }
            set
            {
                _DisplayMemberPath = value;
            }
        }

        private object __SelectedItem;

        /// <summary>
        /// 텍스트박스와 동일한 개체 받아오기
        /// </summary>
        public object SelectedItem
        {
            get
            {
                try
                {
                    var query = (from c in __AutoComplateBindingDataSourceList
                                 where c.ToString() == this.__TextBox.Text.Trim()
                                 select c).Single();
                    return ((AutoComplateBindingData)query).ObjectData;
                }
                catch
                {
                    return null;
                }

            }
            set { __SelectedItem = value; }
        }

        /// <summary>
        /// 텍스트박스 텍스트 세팅
        /// </summary>
        public string Text
        {
            get { return this.__TextBox.Text; }
            set { this.__TextBox.Text = value; }
        }
    }

    /// <summary>
    /// 자동완성에 바인딩 될 데이터소스
    /// </summary>
    public class AutoComplateBindingData
    {
        private string __propertyName;
        private Type __type;
        private Object __ObjectData;

        public Object ObjectData
        {
            get { return __ObjectData; }
            set { __ObjectData = value; }
        }

        /// <summary>
        /// 자동완성에 바인딩 될 데이터소스
        /// </summary>
        /// <param name="member">바인딩될 객체</param>
        /// <param name="propertyName">검색 리스트에 표시될 프로퍼티 이름</param>
        public AutoComplateBindingData(Object member, string propertyName)
        {
            if (null == member)
            {
                throw new ArgumentNullException("member");
            }

            if (String.IsNullOrWhiteSpace(propertyName))
            {
                throw new ArgumentNullException("propertyName");
            }

            __type = member.GetType();
            __ObjectData = member;
            __propertyName = propertyName;

        }

        public override string ToString()
        {
            Object value = __type.GetProperty(
                __propertyName,
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(__ObjectData, new Object[] { });

            return (value ?? String.Empty).ToString();
        }

    }

}

+ Recent posts