WPF Combobox Filter 사용법이 궁금합니다.

안녕하세요. Combobox 아이템이 너무 많아 필터기능을 넣고자 하는데 생각만큼 쉽지가 않네요;;

막연하게 바인딩 소스에 필터를 적용해서 갱신을 했더니 초기화가 안되는 문제가 있어서

이것저것 찾아보다 Filter라는 기능과 예제 소스를 찾게 되었는데 계속해서 NotSupporedException 에러

가 뜨면서 작동이 안되네요. 도움부탁드립니다~!

    <DataGridComboBoxColumn x:Name="bizColumn" Header="업 체" Width="0.3*" CellStyle="{StaticResource gridCellStyle}"
        SelectedValueBinding="{Binding ItemInBiz , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}"
        DisplayMemberPath="Display"
        SelectedValuePath="Value">
        
        <DataGridComboBoxColumn.ElementStyle>
           <Style TargetType="{x:Type ComboBox}">
                <Setter Property="Width" Value="170"/>
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
                <Setter Property="ItemsSource" Value="{Binding FilteredBizList}" />
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>                 
                <Setter Property="ItemContainerStyle" Value="{StaticResource itemcontainer}"/>
                <Setter Property="IsTextSearchEnabled" Value="False"/>
                <EventSetter Event="KeyUp" Handler="Combobox_keyup"/>
       </Style>
 </DataGridComboBoxColumn.ElementStyle>

 <DataGridComboBoxColumn.EditingElementStyle>
     <Style TargetType="{x:Type ComboBox}" >
         <Setter Property="Width" Value="160"/>
          <Setter Property="ItemsSource" Value="{Binding FilteredBizList}" />
         <Setter Property="HorizontalContentAlignment" Value="Center"/>
         <Setter Property="VerticalContentAlignment" Value="Center"/>
         <Setter Property="ItemContainerStyle" Value="{StaticResource itemcontainer}"/>
         <Setter Property="HorizontalAlignment" Value="Center"/>
         <Setter Property="VerticalAlignment" Value="Center"/>
          <Setter Property="IsEditable" Value="True"/>
          <Setter Property="IsTextSearchEnabled" Value="False"/>
         <EventSetter Event="KeyUp" Handler="Combobox_keyup" />
         </Style>
 </DataGridComboBoxColumn.EditingElementStyle>

//Filterd BizList
  BizList = new BindingList<object>();
  BizList.Add(new { Display = "하하", Value = "12345" });
  BizList.Add(new { Display = "호호", Value = "67890" });
  BizList.Add(new { Display = "카캬", Value = "AAAAA" });
  BizList.Add(new { Display = "푸푸", Value = "BBBBB" });
  BizList.Add(new { Display = "소소", Value = "CCCCC" });

//KeyUpEvent Handler
 private void Combobox_keyup(object sender , KeyEventArgs e) 
 {
     ComboBox comboBox = sender as ComboBox;
     comboBox.Items.Filter  -= this.FilterPredicate; //NotSupport 에러
     this.mTextBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;

    

     if (e.Key == Key.Enter || e.Key == Key.Tab || e.Key == Key.Return)
     {
         return;

     }
     else 
     {
         comboBox.IsDropDownOpen = true;
         comboBox.Items.Filter += this.FilterPredicate; //NotSupport 에러
      }

  
 }

//FilterPredicate
    private bool FilterPredicate(object obj) 
    {
        string sValue = string.Empty;

        if (obj is string)
            sValue = obj.ToString();
        else if (obj is ComboBoxItem)
            sValue = (obj as ComboBoxItem).Content.ToString();
        else 
        {
            System.Reflection.PropertyInfo info = obj.GetType().GetProperty(bizColumn.DisplayMemberPath);
            if (info != null) 
            {
                object oValue = info.GetValue(obj, null);
                if (oValue != null) 
                {
                    sValue = oValue.ToString();
                }
            }
  
        }

        if (!string.IsNullOrEmpty(sValue) && sValue.Contains(this.mTextBox.Text)) return true; else return false;
    
    }

}


2개의 좋아요

제가 틀렸다면 죄송합니다.
Filter를 해서 리스트를 보이는건가요? 아니면 타이핑한 글자를 자동 완성하는 기능인가요?

ComboBox x:Name=“ComboTest” Height=“50” Width=“300” DisplayMemberPath=“Name” IsTextSearchEnabled=“True” TextSearch.TextPath=“Name” IsEditable=“True” IsDropDownOpen=“True” StaysOpenOnEdit=“True”

private ObservableCollection name = new ObservableCollection();

        name.Add(new Person("John", 30));
        name.Add(new Person("Daniel", 31));
        name.Add(new Person("Smith", 32));
        name.Add(new Person("Marry", 25));
        name.Add(new Person("Sarah", 20));

        ComboTest.ItemsSource = name;

public class Person
{
public string Name { get; set; }

public int Age { get; set; }

public Person(string name, int age)
{
    Name = name;
    Age = age;
}

}
말씀하신게 이게 맞는지 모르겠습니다. 짧게 만든거라, 만약 틀리다면 알려주세요

2개의 좋아요

안녕하세요. 필터를 해서 리스트가 보이는 겁니다. Text 문자열이 포함된 item이 보이면 됩니다~!

2개의 좋아요

위에 제공해주신 예제로는 동작 되지 않습니다.

혹시나해서
텍스박스 하나, 콤보박스 하나와
위에 주신 비하인드코드 영역부분으로 정상적으로 동작되었습니다!

구성되는 화면이라던가 힌트를 더 주셨으면 하네요!

3개의 좋아요

안녕하세요. 별도의 텍스트박스를 만드는게 아닌 콤보박스의 에디트 기능을 이용하고자 합니다. 예제코드를 참고하여 구현을 했는데 ComboBox의 item의 필터가 적용되지 않고 NotSupport 에러가 발생합니다. (주석참조) 도통 이유를 모르겠네요. 다만 인터넷의 예제와 제 소스 차이점은 Combox item 바인딩 개체가 저는 BindingList이고 인터넷 예제는 List로 되어있습니다. BindingList로 Item을 등록했을 경우에는 Filter를 지원을 안하는건지… 허허;;

3개의 좋아요

아하!
일단 콤보박스의 에디트 기능으로 구현해서 테스트해봤는데
차이점이라고 한다면 DataGrid의 Combox를 사용하지 않았습니다!

한번 비교해서 봐보세요!
XAML

<Window
    x:Class="ComboboxFilterTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:ComboboxFilterTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Window.Resources>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="Width" Value="170" />
            <Setter Property="Height" Value="21" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="5" />
            <ColumnDefinition Width="auto" />
        </Grid.ColumnDefinitions>
        <ComboBox
            x:Name="bizColumn"
            Grid.Column="2"
            DisplayMemberPath="Display"
            IsEditable="True"
            ItemsSource="{Binding BizList}"
            KeyUp="bizColumn_KeyUp" />
    </Grid>
</Window>

behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent ();
        this.DataContext = new MainViewModel ();
    }

    private bool FilterPredicate(object obj)
    {
        string sValue = string.Empty;

        if (obj is string)
            sValue = obj.ToString ();
        else if (obj is ComboBoxItem)
            sValue = (obj as ComboBoxItem).Content.ToString ();
        else
        {
            System.Reflection.PropertyInfo info = obj.GetType ().GetProperty (bizColumn.DisplayMemberPath);
            if (info != null)
            {
                object oValue = info.GetValue (obj, null);
                if (oValue != null)
                {
                    sValue = oValue.ToString ();
                }
            }

        }

        if (!string.IsNullOrEmpty (sValue) && sValue.Contains (tb.Text))
            return true;
        else
            return false;

    }
    TextBox tb;
    private void bizColumn_KeyUp(object sender, KeyEventArgs e)
    {
        ComboBox comboBox = sender as ComboBox;
        comboBox.Items.Filter -= this.FilterPredicate; //NotSupport 에러
        tb = comboBox.Template.FindName ("PART_EditableTextBox", comboBox) as TextBox;



        if (e.Key == Key.Enter || e.Key == Key.Tab || e.Key == Key.Return)
        {
            return;

        }
        else
        {
            comboBox.IsDropDownOpen = true;
            comboBox.Items.Filter += this.FilterPredicate; //NotSupport 에러
        }


    }
}

viewmodel

public class bizModel
{
    public string Display { get; set; }
    public string Value { get; set; }
}
public partial class MainViewModel :ObservableObject
{
    [ObservableProperty] List<bizModel> bizList;
    public MainViewModel()
    {
        BizList = new ();
        BizList.Add (new bizModel { Display = "하하", Value = "12345" });
        BizList.Add (new bizModel { Display = "호호", Value = "67890" });
        BizList.Add (new bizModel { Display = "카캬", Value = "AAAAA" });
        BizList.Add (new bizModel { Display = "푸푸", Value = "BBBBB" });
        BizList.Add (new bizModel { Display = "소소", Value = "CCCCC" });
    }
}

Screenshot 2023-12-19 at 10.46.40

4개의 좋아요

DataGrid의 Combox컬럼이 문제였군요 ㅠㅠ 그리드에 칼럼추가해서 Test해봐야 겠습니다. 예제코드 작동영상까지 너무 너무 감사합니다~!!

2개의 좋아요