1

概要:リストボックスアイテムをクリックすると、DataTemplateのテキストボックスがフォーカスされますが、リストボックスアイテムは選択されていません。

これはイベントのバブリングと関係があると確信していますが、ここで何かが欠けています。

私はリストボックスを持っています。各ListBoxItemのContentTemplateは、単純なテキストボックスを含むDataTemplateに割り当てられます。

このTextBoxは、偽の編集可能なラベルとして表示されるように設計されています。

問題:テキストボックスをクリックすると、リストボックスのselectedItemが更新されません。テキストボックスはmousedownイベントを飲み込んでおり、リストボックスに新しいアイテムに更新するように通知されることはありません。

私はここで愚かな何かを逃しているような気がします。何か案は?イベントを強制的に親のListViewにバブルアップさせる方法はありますか?

テキストボックスの背景をNullにすることから、previewmousedownイベントを処理し、e.handled = false;を設定することまで、すべてを試しました。

DataTemplate:

<DataTemplate x:Key="ItemTempl">
            <TextBox Height="20" Width="200" Name="tbox" Text="{Binding WordText}" HorizontalAlignment="Stretch">
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="BorderThickness" Value="0"/>
                        <Setter Property="Background" Value="{x:Null}"/>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=IsFocused, ElementName=tbox}" Value="True">
                                <Setter Property="BorderThickness" Value="1"/>
                                <Setter Property="Background" Value="White"/>                                    
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
</DataTemplate>

リストビュー:

<ListView HorizontalAlignment="Stretch" ItemsSource="{Binding Something.Words}" Name="MainListView" SelectedItem="{Binding CurrentItem, Mode=TwoWay}" BorderThickness="0" ItemContainerStyle="{StaticResource ContainerStyle}">
</ListView>
4

2 に答える 2

2

プレビューマウスダウンイベントを処理してアイテムを選択する独自のリストビューを作成することで、ListViewに関するこの特定の問題を回避しました。これを状況に適応させることができます。おそらく、添付のプロパティでこれを行うのが最善であり、そうしないでください。新しいクラスを作成する必要があります。

基本的に、マウスダウンの元のソースであるテキストボックスを探し、ビジュアルツリーヘルパーを使用して、そのビジュアルツリーを、それが置かれているリストビューアイテムまでさかのぼって追跡し、選択します。

 public class MyListView : ListView
    {
        protected override void OnPreviewMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        {
            DependencyObject listViewItem = (DependencyObject)e.OriginalSource;
            while (listViewItem != null && !(listViewItem is ListViewItem))
                listViewItem = VisualTreeHelper.GetParent(listViewItem);

            SelectedItem = ((ListViewItem)listViewItem).Content;

            base.OnPreviewMouseDown(e);
        }
    }

編集:これは添付のプロパティバージョンです。

public class ListViewExtras : DependencyObject
    {
        public static bool GetWillAlwaysSelect(DependencyObject obj)
        {
            return (bool)obj.GetValue(WillAlwaysSelectProperty);
        }

        public static void SetWillAlwaysSelect(DependencyObject obj, bool value)
        {
            obj.SetValue(WillAlwaysSelectProperty, value);
        }

        // Using a DependencyProperty as the backing store for WillAlwaysSelect.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WillAlwaysSelectProperty =
            DependencyProperty.RegisterAttached("WillAlwaysSelect", typeof(bool), typeof(ListViewExtras), new PropertyMetadata(false, new PropertyChangedCallback((s, e) =>
            {
                ListView listView = s as ListView;
                if (listView != null)
                {
                    if ((bool)e.NewValue) listView.PreviewMouseDown += listView_PreviewMouseDown;
                    if (!(bool)e.NewValue && (bool)e.OldValue) listView.PreviewMouseDown -= listView_PreviewMouseDown;
                }
            })));

        static void listView_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ListView listView = sender as ListView;
            if (listView != null)
            {
                DependencyObject listViewItem = (DependencyObject)e.OriginalSource;
                while (listViewItem != null && !(listViewItem is ListViewItem))
                    listViewItem = VisualTreeHelper.GetParent(listViewItem);
                listView.SelectedItem = ((ListViewItem)listViewItem).Content;
            }
        }
    }

と一緒に使用します

<ListView HorizontalContentAlignment="Stretch" local:ListViewExtras.WillAlwaysSelect="True">
于 2012-11-27T16:51:27.483 に答える
1

ContainerFromElementメソッドとItemContainerGenerator.IndexFromContainerメソッドを使用して、セレクターをより一般的にサポートするようにイベントハンドラーを変更しました。

    private static void OnPreviewListBoxMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        var listBox = sender as Selector;
        if (listBox != null)
        {
            DependencyObject mouseItem = e.OriginalSource as DependencyObject;
            if (mouseItem != null)
            {
                // Get the container based on the element
                var container = listBox.ContainerFromElement(mouseItem);
                if (container != null)
                {
                    var index = listBox.ItemContainerGenerator.IndexFromContainer(container);
                    Debug.Assert(index >= 0);
                    listBox.SelectedIndex = index;
                }
            }
        }
    }
于 2013-08-22T20:50:48.227 に答える