トップ回答者
listbox内のTextboxにカーソルを持っていく

質問
-
環境はVisualStudio.net VB 2010です。
表題の処理ができずに困っております。
Listboxには画像とTextboxが対になる形で配置してあり、入力する画像を増やすと
左記ペアが1個ずつ増えていくものです。
この時ListBox内のある項目を選択時にキーボードの上下を押すとそのイベントをもって
押されたキーが上下ならばListboxの選択されている項目が上下に移動するコードを実装し、
動くところまではできたのですが、そのListBox内にあるテキストボックスにカーソルを
もっていく方法がわかりません。
諸先輩方、単純な質問かとは思いますがご教授なにとぞよろしくお願いします。
ソースコード部を下記します。
lstFName.SelectedIndex = 0 ’選択項目の指定
lstFName.Items(selnum).→この後にどのようにTextbox指定すればよいかがわかりません。TextboxのWPFコード部の宣言は下記となります。
<TextBox x:Name="TxtFilename" Text="{Binding Path=ttt,UpdateSourceTrigger=PropertyChanged}"
Grid.Row="3" Width="auto"></TextBox>
回答
-
おそらく以下の感じでできると思いますが、サンプルコードがC#です。VBに変換できますか?
Set Focus of TextBox in ListView
https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e9a98c3-b4be-40af-99bd-828491ddcd69/set-focus-of-textbox-in-listview?forum=wpf★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月10日 0:27
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月4日 8:07
-
こんな?
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel> <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5"> <CheckBox Content="並び順を変更する" x:Name="chkSwap"/> </StackPanel> <ListBox ItemsSource="{Binding Path=Items}" x:Name="lstFName"> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <EventSetter Event="PreviewKeyDown" Handler="ListBoxItem_PreviewKeyDown" /> <EventSetter Event="GotKeyboardFocus" Handler="ListBoxItem_GotKeyboardFocus" /> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="true"> <Setter Property="IsSelected" Value="True" /> </Trigger> </Style.Triggers> </Style> </ListBox.ItemContainerStyle> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Border BorderBrush="Black" BorderThickness="1" Background="LightGray"> <Image Width="50" Height="50" x:Name="thisIsDummy"/> </Border> <TextBox x:Name="TxtFilename" Text="{Binding Path=ttt,UpdateSourceTrigger=PropertyChanged}" Grid.Row="3" Width="auto"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </DockPanel> </Window>
Class MainWindow Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 Me.DataContext = Model.CreateTestModel() End Sub Private Sub ListBoxItem_PreviewKeyDown(sender As System.Object, e As System.Windows.Input.KeyEventArgs) Dim container As ListBoxItem = CType(sender, ListBoxItem) Dim index = Me.lstFName.ItemContainerGenerator.IndexFromContainer(container) If (Me.chkSwap.IsChecked) Then '並び順を入れ替える場合 Dim item As Object = Me.lstFName.ItemContainerGenerator.ItemFromContainer(container) Dim list As System.Collections.IList = Me.lstFName.ItemsSource If (e.Key = Key.Up AndAlso 0 < index) Then list.RemoveAt(index) index = index - 1 list.Insert(index, item) ElseIf (e.Key = Key.Down AndAlso index < Me.lstFName.Items.Count - 1) Then list.RemoveAt(index) index = index + 1 list.Insert(index, item) Else Exit Sub End If '選択対象を変更してそこまでスクロール Me.lstFName.SelectedIndex = index Me.lstFName.ScrollIntoView(Me.lstFName.SelectedItem) '選択した項目にフォーカスを container = Me.lstFName.ItemContainerGenerator.ContainerFromIndex(Me.lstFName.SelectedIndex) If (container IsNot Nothing) Then container.Focus() End If e.Handled = True Else '単純にListBoxの選択状態を上下させるだけ Dim request As TraversalRequest If (e.Key = Key.Up) Then request = New TraversalRequest(FocusNavigationDirection.Up) ElseIf (e.Key = Key.Down) Then request = New TraversalRequest(FocusNavigationDirection.Down) Else Exit Sub End If Dim ui As UIElement = TryCast(Keyboard.FocusedElement, UIElement) If (ui IsNot Nothing) Then ui.MoveFocus(request) e.Handled = True End If End If End Sub Private Sub ListBoxItem_GotKeyboardFocus(sender As System.Object, e As System.Windows.Input.KeyboardFocusChangedEventArgs) 'ListBoxItemにフォーカスが Dim container As ListBoxItem = CType(sender, ListBoxItem) If (Keyboard.FocusedElement Is container) Then 'キーボードフォーカスがListBoxItemにあるならTextBoxをさがして Dim cp As ContentPresenter = FindChild(Of ContentPresenter)(container) If (cp IsNot Nothing) Then Dim txb As TextBox = TryCast(cp.ContentTemplate.FindName("TxtFilename", cp), TextBox) If (txb IsNot Nothing AndAlso Not txb.IsKeyboardFocused) Then 'フォーカスをセット txb.Focus() txb.SelectAll() e.Handled = True End If End If End If End Sub ''' <summary>子要素を探す</summary> Private Function FindChild(Of T As DependencyObject)(ByVal d As DependencyObject) As DependencyObject Dim count As Integer = VisualTreeHelper.GetChildrenCount(d) For i As Integer = 0 To count - 1 Dim ret As T Dim child As DependencyObject child = VisualTreeHelper.GetChild(d, i) ret = TryCast(child, T) If (ret Is Nothing) Then ret = FindChild(Of T)(child) End If If (ret IsNot Nothing) Then Return ret End If Next Return Nothing End Function End Class Class Model Public Property Items As New System.Collections.ObjectModel.ObservableCollection(Of Item) Public Shared Function CreateTestModel() As Model Dim m As New Model For i As Integer = 1 To 100 m.Items.Add(New Item() With {.ttt = i.ToString()}) Next Return m End Function End Class Class Item Implements System.ComponentModel.INotifyPropertyChanged Public Property ttt As String Get Return _ttt End Get Set(value As String) _ttt = value OnPropertyChagned("ttt") End Set End Property Private _ttt As String Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Protected Sub OnPropertyChagned(ByVal name As String) RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name)) End Sub End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月10日 0:27
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月4日 8:06
すべての返信
-
おそらく以下の感じでできると思いますが、サンプルコードがC#です。VBに変換できますか?
Set Focus of TextBox in ListView
https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e9a98c3-b4be-40af-99bd-828491ddcd69/set-focus-of-textbox-in-listview?forum=wpf★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月10日 0:27
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月4日 8:07
-
こんな?
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel> <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5"> <CheckBox Content="並び順を変更する" x:Name="chkSwap"/> </StackPanel> <ListBox ItemsSource="{Binding Path=Items}" x:Name="lstFName"> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <EventSetter Event="PreviewKeyDown" Handler="ListBoxItem_PreviewKeyDown" /> <EventSetter Event="GotKeyboardFocus" Handler="ListBoxItem_GotKeyboardFocus" /> <Style.Triggers> <Trigger Property="IsKeyboardFocusWithin" Value="true"> <Setter Property="IsSelected" Value="True" /> </Trigger> </Style.Triggers> </Style> </ListBox.ItemContainerStyle> <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Border BorderBrush="Black" BorderThickness="1" Background="LightGray"> <Image Width="50" Height="50" x:Name="thisIsDummy"/> </Border> <TextBox x:Name="TxtFilename" Text="{Binding Path=ttt,UpdateSourceTrigger=PropertyChanged}" Grid.Row="3" Width="auto"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </DockPanel> </Window>
Class MainWindow Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 Me.DataContext = Model.CreateTestModel() End Sub Private Sub ListBoxItem_PreviewKeyDown(sender As System.Object, e As System.Windows.Input.KeyEventArgs) Dim container As ListBoxItem = CType(sender, ListBoxItem) Dim index = Me.lstFName.ItemContainerGenerator.IndexFromContainer(container) If (Me.chkSwap.IsChecked) Then '並び順を入れ替える場合 Dim item As Object = Me.lstFName.ItemContainerGenerator.ItemFromContainer(container) Dim list As System.Collections.IList = Me.lstFName.ItemsSource If (e.Key = Key.Up AndAlso 0 < index) Then list.RemoveAt(index) index = index - 1 list.Insert(index, item) ElseIf (e.Key = Key.Down AndAlso index < Me.lstFName.Items.Count - 1) Then list.RemoveAt(index) index = index + 1 list.Insert(index, item) Else Exit Sub End If '選択対象を変更してそこまでスクロール Me.lstFName.SelectedIndex = index Me.lstFName.ScrollIntoView(Me.lstFName.SelectedItem) '選択した項目にフォーカスを container = Me.lstFName.ItemContainerGenerator.ContainerFromIndex(Me.lstFName.SelectedIndex) If (container IsNot Nothing) Then container.Focus() End If e.Handled = True Else '単純にListBoxの選択状態を上下させるだけ Dim request As TraversalRequest If (e.Key = Key.Up) Then request = New TraversalRequest(FocusNavigationDirection.Up) ElseIf (e.Key = Key.Down) Then request = New TraversalRequest(FocusNavigationDirection.Down) Else Exit Sub End If Dim ui As UIElement = TryCast(Keyboard.FocusedElement, UIElement) If (ui IsNot Nothing) Then ui.MoveFocus(request) e.Handled = True End If End If End Sub Private Sub ListBoxItem_GotKeyboardFocus(sender As System.Object, e As System.Windows.Input.KeyboardFocusChangedEventArgs) 'ListBoxItemにフォーカスが Dim container As ListBoxItem = CType(sender, ListBoxItem) If (Keyboard.FocusedElement Is container) Then 'キーボードフォーカスがListBoxItemにあるならTextBoxをさがして Dim cp As ContentPresenter = FindChild(Of ContentPresenter)(container) If (cp IsNot Nothing) Then Dim txb As TextBox = TryCast(cp.ContentTemplate.FindName("TxtFilename", cp), TextBox) If (txb IsNot Nothing AndAlso Not txb.IsKeyboardFocused) Then 'フォーカスをセット txb.Focus() txb.SelectAll() e.Handled = True End If End If End If End Sub ''' <summary>子要素を探す</summary> Private Function FindChild(Of T As DependencyObject)(ByVal d As DependencyObject) As DependencyObject Dim count As Integer = VisualTreeHelper.GetChildrenCount(d) For i As Integer = 0 To count - 1 Dim ret As T Dim child As DependencyObject child = VisualTreeHelper.GetChild(d, i) ret = TryCast(child, T) If (ret Is Nothing) Then ret = FindChild(Of T)(child) End If If (ret IsNot Nothing) Then Return ret End If Next Return Nothing End Function End Class Class Model Public Property Items As New System.Collections.ObjectModel.ObservableCollection(Of Item) Public Shared Function CreateTestModel() As Model Dim m As New Model For i As Integer = 1 To 100 m.Items.Add(New Item() With {.ttt = i.ToString()}) Next Return m End Function End Class Class Item Implements System.ComponentModel.INotifyPropertyChanged Public Property ttt As String Get Return _ttt End Get Set(value As String) _ttt = value OnPropertyChagned("ttt") End Set End Property Private _ttt As String Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Protected Sub OnPropertyChagned(ByVal name As String) RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name)) End Sub End Class
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月10日 0:27
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月4日 8:06
-
pen800 さん、こんにちは
フォーラム オペレーターの立花楓です。
本件についてその後いかがでしょうか。
trapemiya さん、gekka さんにお寄せいただいた情報がご参考になると思いましたので、こちらで回答マークを付けさせていただきました。なにか進展がございましたらこちらのスレッドへご返信いただけますと幸いです。
よろしくお願いします。
MSDN/TechNet Community Support 立花楓
- 編集済み 立花楓Microsoft employee, Moderator 2017年8月4日 8:06