none
WPF ToolkitのAutoCompleteBoxでItemsSourceを動的に変更させたい。 RRS feed

  • 質問

  • この内容をここで質問していいのか分かりませんが、分かる方おられましたら助けてください。
    また、ほかの方法ありましたら教えてください。

    ◎実装したい機能
    現在、AutoCompleteBoxを使って、名前の検索機能を実装しようとしております。
    入力した「ひらがな」からDBを検索してその結果の漢字を一覧に表示させて選択するイメージです。

    ◎実装方法
    TextChangedのイベントで入力した値からDBを検索してその結果をItemsSourceにセットする方法で試みています。

    ◎問題点
    ・「あ」と入力後に一覧に候補が出てくるので、Enterキーで「あ」の入力を確定。
     矢印キーで一覧から対象の漢字を選択。
     その状態でEnterキーを押さずに「あ」の続き文字を入力するとシステムエラーが発生します。

    下にソースを記述します。

    <XAML>

    <Window x:Class="Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
        Title="Window2" Height="300" Width="300">
    
        <Window.Resources>
            <DataTemplate x:Key="AutoCompleteBoxItemTemplate">
                <Label Content="{Binding KANJI}" />
            </DataTemplate>
        </Window.Resources>
    
        <Grid>
            
            <toolkit:AutoCompleteBox Name="autocompleteBox"
                                     ItemTemplate="{StaticResource ResourceKey=AutoCompleteBoxItemTemplate}"
                                     VerticalAlignment="Center"
                                     Width="100"/>
        </Grid>
    </Window>
    

    <コードビハインド>

    Public Class Window2
    
        Private lstT_NAME As List(Of T_NAME)
    
        Public Sub New()
    
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
    
            TextCompositionManager.AddPreviewTextInputHandler(autocompleteBox, AddressOf OnPreviewTextInput)
            TextCompositionManager.AddPreviewTextInputStartHandler(autocompleteBox, AddressOf OnPreviewTextInputStart)
            TextCompositionManager.AddPreviewTextInputUpdateHandler(autocompleteBox, AddressOf OnPreviewTextInputUpdate)
    
            autocompleteBox.ItemFilter = AddressOf NameFilter
    
            lstT_NAME = T_NAME.CreateTestData
    
        End Sub
    
        Private _imeFlag As Boolean = False
    
        Private Function NameFilter(userInput As String, item As Object) As Boolean
            Return True
        End Function
    
        Private Sub OnPreviewTextInputStart(sender As Object, e As TextCompositionEventArgs)
            _imeFlag = True
            Debug.WriteLine("OnPreviewTextInputStart")
        End Sub
    
        Private Overloads Sub OnPreviewTextInput(sender As Object, e As TextCompositionEventArgs)
            _imeFlag = False
            Debug.WriteLine("OnPreviewTextInput")
        End Sub
    
        Private Sub OnPreviewTextInputUpdate(sender As Object, e As TextCompositionEventArgs)
            If e.TextComposition.CompositionText.Length = 0 Then
                _imeFlag = False
                Debug.WriteLine("OnPreviewTextInputUpdate")
            End If
        End Sub
    
        Private Sub autocompleteBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles autocompleteBox.SelectionChanged
            _imeFlag = False
            Debug.WriteLine("SelectionChanged")
        End Sub
    
        Private Sub autocompleteBox_TextChanged(sender As Object, e As RoutedEventArgs) Handles AutoCompleteBox.TextChanged
    
            Try
    
                Debug.WriteLine("TextChanged")
    
                If _imeFlag = False Then
                    Exit Try
                End If
    
                Dim txt As System.Windows.Controls.AutoCompleteBox = DirectCast(sender, System.Windows.Controls.AutoCompleteBox)
                Dim val As String = txt.Text.Replace(" ", " ")
    
                Debug.WriteLine("TextChanged (" & txt.Text)
    
                If val.Length = 0 Then
                    Exit Try
                End If
    
                Dim lst As New List(Of T_NAME)
    
    
                lst = lstT_NAME.Where(Function(item) item.KANA.StartsWith(val)).ToList
    
                autocompleteBox.ItemsSource = lst
                autocompleteBox.ValueMemberPath = "KANJI"
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
    
        End Sub
    
    
        Public Class T_NAME
    
            Private _KANA As String
            Private _KANJI As String
    
            Public Sub New()
                _KANA = ""
                _KANJI = ""
            End Sub
    
            Public Property KANA As String
                Get
                    Return _KANA
                End Get
                Set(ByVal value As String)
                    If Not value.Equals(_KANA) Then
                        _KANA = value
                    End If
                End Set
            End Property
    
            Public Property KANJI As String
                Get
                    Return _KANJI
                End Get
                Set(ByVal value As String)
                    If Not value.Equals(_KANJI) Then
                        _KANJI = value
                    End If
                End Set
            End Property
    
    
            Public Shared Function CreateTestData() As List(Of T_NAME)
                Dim items As List(Of T_NAME) = New List(Of T_NAME)()
                Dim item As T_NAME
    
                item = New T_NAME
                item.KANA = "あいだ"
                item.KANJI = "相田"
                items.Add(item)
    
                item = New T_NAME
                item.KANA = "あおき"
                item.KANJI = "青木"
                items.Add(item)
    
                item = New T_NAME
                item.KANA = "あかぎ"
                item.KANJI = "赤城"
                items.Add(item)
    
                Return items
            End Function
    
        End Class
    
    End Class
    

    2016年8月4日 10:18

回答

  • TextChangedイベントではなくPopulatingイベントで処理します。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク u.daichi 2016年8月5日 2:16
    2016年8月4日 12:32

すべての返信

  • TextChangedイベントではなくPopulatingイベントで処理します。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク u.daichi 2016年8月5日 2:16
    2016年8月4日 12:32
  • gekka 様

    処理をPopulatingイベントに移動させたら思っている通りの動作になりました。
    いつも本当にありがとうございます。
    2016年8月5日 2:17