wpf 在列錶框中選擇文本框項目不會更改列錶框的選定項目




xaml listbox (12)

我有一個wpf列錶框,顯示一個文本框列表。 當我單擊文本框時,列錶框選擇不會更改。 我必須單擊TextBox旁邊的以選擇列錶框項。 是否需要為Textbox設置一些屬性以將click事件轉發到Listbox?


Answer #1

我沒有足夠的代表發表評論,所以我發表評論作為答案。 Grazer的上述解決方案在您有另一個控件(例如需要SelectedItemButton情況下不起作用。 這是因為根據Style Trigger ,單擊該ButtonIsKeyboardFocusWithin變為false,並且SelectedItem變為null。


Answer #2

舊討論,但也許我的回答有助於其他人......

Ben的解決方案與Grazer的解決方案具有相同的問題。 不好的是,選擇取決於文本框的[鍵盤]焦點。 如果您的對話框上有另一個控件(即按鈕),則單擊該按鈕時焦點會丟失,並且listboxitem將被取消選中(SelectedItem == null)。 因此,您可以通過單擊項目(文本框外部)並單擊文本框來執行不同的操作。 處理起來非常繁瑣,看起來很奇怪。

我很確定沒有純XAML解決方案。 我們需要代碼隱藏。 解決方案接近Mark所建議的。

(在我的示例中,我使用ListViewItem而不是ListBoxItem,但解決方案適用於兩者)。

代碼隱藏:

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"/>

Answer #3

試試這段代碼:

foreach (object item in this.listBox1.Items) {
    if (textbox1.text.equals(item.toString())) {
        //show error message; break
    }
}

Answer #4

以下是@ Ben的答案的簡化,而不必覆蓋DataTemplate。 它甚至可以作為靜態樣式應用。 使用包含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>

Answer #5

是否需要為Textbox設置一些屬性以將click事件轉發到Listbox?

它不是一個簡單的屬性,但您可以在TextBox上處理GotFocus事件,然後使用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;
}


Answer #7

我能夠找到的最簡單的方法是使用PreviewMouseDown事件並設置模板化父級的IsSelected屬性。 由於預覽事件會向下冒泡,因此只要用戶單擊文本框,組合框或您設置事件的任何其他控件,ListBoxItem就會處理該事件。

關於這一點的一個好處是你可以對所有類型的控件使用相同的事件,因為它們都派生自Framework元素。 此外,當您將列錶框的SelectionMode設置為“Extended”時,設置IsSelected(而不是設置SelectedItem)將導致選擇多個項目,這可能是也可能不是您要查找的內容。

即:

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"/>
    ...

Answer #8

列錶框處理項目選擇,但不知道嵌入其中的文本框的焦點。 如果要在文本框獲得輸入焦點時更改選擇,則需要手動更改列錶框選擇,afaik。


Answer #9

我使用類似於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屬性的setter。 你應該在xmlns:behave="clr-namespace:MyBehaviours"引用它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>

Answer #10

請務必使用適當的TargetType:ListViewItem,ListBoxItem或TreeViewItem。

<Style TargetType="ListViewItem">
    <Style.Triggers>
        <Trigger Property="IsKeyboardFocusWithin" Value="true">
            <Setter Property="IsSelected" Value="true" />
        </Trigger>
    </Style.Triggers>
</Style>

Answer #11

我們使用以下樣式來設置PreviewGotKeyboardFocus,它處理TextBox控件和ComboBoxes的所有事件,如下所示:

    <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;
    }

Answer #12

你對初始情況不太了解。 但我假設您使用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) */
}




selecteditem