テキストボックスのリストを表示するwpfリストボックスがあります。テキストボックスをクリックしても、リストボックスの選択は変わりません。 TextBoxの横をクリックしてリストボックス項目を選択する必要があります。 TextboxがクリックイベントをListboxに転送するために設定する必要があるプロパティはありますか?
次のスタイルを使用して、TextBoxコントロールやComboBoxなどのすべてのイベントを処理するPreviewGotKeyboardFocusを設定します。
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewGotKeyboardFocus" Handler="SelectCurrentItem"/>
</Style>
</ListView.ItemContainerStyle>
次に、コードビハインドで行を選択します。
protected void SelectCurrentItem(object sender, KeyboardFocusChangedEventArgs e)
{
ListViewItem item = (ListViewItem) sender;
item.IsSelected = true;
}
必ず適切なTargetType(ListViewItem、ListBoxItem、またはTreeViewItem)を使用してください。
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
</Style.Triggers>
</Style>
コメントするのに十分な担当者がいないので、コメントを回答として投稿しています。上記のGrazerのソリューションは、Button
を必要とするSelectedItem
などの別のコントロールがある場合は機能しません。これは、Style Trigger
、そのIsKeyboardFocusWithin
をクリックするとButton
がfalseになり、SelectedItem
がnullになります。
私はRobertのソリューションと同様に使用しましたが、コードビハインドなし(アタッチされた動作を使用)です。
そうするために、
最初。別のクラスFocusBehaviourを作成します。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace MyBehaviours
{
public class FocusBehaviour
{
#region IsFocused
public static bool GetIsFocused(Control control)
{
return (bool) control.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(Control control, bool value)
{
control.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
"IsFocused",
typeof(bool),
typeof(FocusBehaviour),
new UIPropertyMetadata(false, IsFocusedPropertyChanged));
public static void IsFocusedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var control = sender as Control;
if (control == null || !(e.NewValue is bool))
return;
if ((bool)e.NewValue && !(bool)e.OldValue)
control.Focus();
}
#endregion IsFocused
#region IsListBoxItemSelected
public static bool GetIsListBoxItemSelected(Control control)
{
return (bool) control.GetValue(IsListBoxItemSelectedProperty);
}
public static void SetIsListBoxItemSelected(Control control, bool value)
{
control.SetValue(IsListBoxItemSelectedProperty, value);
}
public static readonly DependencyProperty IsListBoxItemSelectedProperty = DependencyProperty.RegisterAttached(
"IsListBoxItemSelected",
typeof(bool),
typeof(FocusBehaviour),
new UIPropertyMetadata(false, IsListBoxItemSelectedPropertyChanged));
public static void IsListBoxItemSelectedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var control = sender as Control;
DependencyObject p = control;
while (p != null && !(p is ListBoxItem))
{
p = VisualTreeHelper.GetParent(p);
}
if (p == null)
return;
((ListBoxItem)p).IsSelected = (bool)e.NewValue;
}
#endregion IsListBoxItemSelected
}
}
二番目。リソースセクションにスタイルを追加します(私のスタイルはフォーカスで黒に丸められます)。 FocusBehaviour.IsListBoxItemSelectedプロパティのセッターに注意してください。 xmlns:behave="clr-namespace:MyBehaviours"
で参照する必要があります
`
<Style x:Key="PreviewTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border
Margin="6,2,0,4"
BorderBrush="#FFBDBEBD"
BorderThickness="1"
CornerRadius="8"
Background="White"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
MinWidth="100"
x:Name="bg">
<ScrollViewer
x:Name="PART_ContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Background" TargetName="bg" Value="Black"/>
<Setter Property="Background" Value="Black"/><!-- we need it for caret, it is black on black elsewise -->
<Setter Property="Foreground" Value="White"/>
<Setter Property="behave:FocusBehaviour.IsListBoxItemSelected" Value="True"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
`
第三。 (オプション、逆タスク用)
ListBoxItemが選択されたときのTextBoxに焦点を当て、逆のタスクはありません。 Behaviorクラスの別のプロパティであるIsFocusedを使用することをお勧めします。これはListBoxItem
のサンプルテンプレートです。Property="behave:FocusBehaviour.IsFocused"
とFocusManager.IsFocusScope="True"
に注意してください
<DataTemplate x:Key="YourKey" DataType="{x:Type YourType}">
<Border
Background="#FFF7F3F7"
BorderBrush="#FFBDBEBD"
BorderThickness="0,0,0,1"
FocusManager.IsFocusScope="True"
x:Name="bd"
MinHeight="40">
<TextBox
x:Name="textBox"
Style="{StaticResource PreviewTextBox}"
Text="{Binding Value}" />
</Border>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter
TargetName="textBox"
Property="behave:FocusBehaviour.IsFocused"
Value="True" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
この動作を設定するには、クラスハンドラーを使用します。このようにすると、アプリケーションのすべてのリストビューが修正されます。これがデフォルトの動作ではない理由がわかりません。
App.xaml.csで、OnStartupに以下を追加します。
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof (ListViewItem),
ListViewItem.PreviewGotKeyboardFocusEvent,
new RoutedEventHandler((x,_) => (x as ListViewItem).IsSelected = true));
}
TextboxがクリックイベントをListboxに転送するために設定する必要があるプロパティはありますか?
これは単純なプロパティではありませんが、GotFocus
で TextBox
イベントを処理し、次に VisualTreeHelper を使用してListBoxItem
を見つけて選択できます。
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox myTextBox = sender as TextBox;
DependencyObject parent = VisualTreeHelper.GetParent(myTextBox);
while (!(parent is ListBoxItem))
{
parent = VisualTreeHelper.GetParent(parent);
}
ListBoxItem myListBoxItem = parent as ListBoxItem;
myListBoxItem.IsSelected = true;
}
これはあなたが探している答えです: その内部のComboBoxがフォーカスされているときにListBoxItemを選択する
以下は、DataTemplateをオーバーライドする必要のない@Benの回答を簡略化したものです。静的なスタイルとしても適用できます。 GridView > GridViewColumn > TextBox
を含むListViewでテストされています。
例:
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
これを行うために見つけた最も簡単な方法は、PreviewMouseDownイベントを使用して、テンプレート化された親のIsSelectedプロパティを設定することです。プレビューイベントはバブルダウンするので、ユーザーがテキストボックス、コンボボックス、またはイベントを設定したその他のコントロールをクリックするとすぐに、ListBoxItemがイベントを処理します。
これの1つの良い点は、すべてのタイプのコントロールがすべてフレームワーク要素から派生しているため、同じタイプのコントロールに同じイベントを使用できることです。また、(SelectedItemを設定する代わりに)IsSelectedを設定すると、リストボックスのSelectionModeを "Extended"に設定したときに複数の項目が選択されます。
つまり:
c#コード
private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
((sender as FrameworkElement).TemplatedParent as ListBoxItem).IsSelected = true;
}
xaml
...
<ComboBox PreviewMouseDown="Element_PreviewMouseDown"/>
<TextBox PreviewMouseDown="Element_PreviewMouseDown"/>
...
古い議論ですが、おそらく私の答えは他の人を助けます...
ベンのソリューションには、グレイザーのソリューションと同じ問題があります。悪い点は、選択がテキストボックスの[キーボード]フォーカスに依存することです。ダイアログに別のコントロール(ボタンなど)がある場合、ボタンをクリックするとフォーカスが失われ、listboxitemが選択解除されます(SelectedItem == null)。そのため、(テキストボックスの外の)アイテムをクリックする場合と、テキストボックスをクリックする場合の動作が異なります。これは処理が非常に退屈で、非常に奇妙に見えます。
このための純粋なXAMLソリューションはないと確信しています。これにはコードビハインドが必要です。解決策はマークが提案したものに近いです。
(私の例では、ListBoxItemの代わりにListViewItemを使用していますが、ソリューションは両方で機能します)。
コードビハインド:
private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var frameworkElement = sender as FrameworkElement;
if (frameworkElement != null)
{
var item = FindParent<ListViewItem>(frameworkElement);
if (item != null)
item.IsSelected = true;
}
}
findParentを使用して( http://www.infragistics.com/community/blogs/blagunas/archive/2013/05/29/find-the-parent-control-of-a-specific-type-in -wpf-and-silverlight.aspx ):
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
return FindParent<T>(parentObject);
}
私のDataTemplateで:
<TextBox Text="{Binding Name}"
PreviewMouseDown="Element_PreviewMouseDown"/>
前の回答で説明したように、選択を直接設定することを完全に確信しているわけではありません。複数選択や他のいくつかのシーンを壊してしまうためです。
。以下のようにボタンのスタイルを変更して、何が起こるか確認してみてください。
<Button ClickMode="Pressed" Focusable="False">
<Button.Template>
<ControlTemplate> // change the template to get rid of all the default chrome
<Border Background="Transparent"> // Button won't be clickable without some kind of background set
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
<TextBox />
このコードを試してください:
foreach (object item in this.listBox1.Items) {
if (textbox1.text.equals(item.toString())) {
//show error message; break
}
}
リストボックスはアイテムの選択を処理しますが、埋め込まれたテキストボックスのフォーカスについては知りません。テキストボックスが入力フォーカスを取得するたびに選択を変更したい場合は、リストボックスの選択を手動で変更する必要があります。
あなたの初期状況についてあまり具体的ではありません。ただし、DataBindingとItemTemplateを使用するとします。これは、このトピックの初心者の場合も同様です。これはうまくいくはずです:
<ListBox ItemsSource="{Binding someDataCollection}" Name="myListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding datafield}" Tag="{Binding .}"
GotFocus="TextBox_GotFocus"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
myListBox.SelectedItem = (sender as TextBox).Tag; /* Maybe you need to cast to the type of the objects contained in the collection(bound as ItemSource above) */
}