Как предотвратить потерю фокуса текстового поля DataTemplate при добавлении элемента в Itemscontrol?

У меня есть ItemsControl с ItemsSource, привязанным к IEnumerable ‹MyDataItem>.

ItemTemplate состоит из двух текстовых полей. (Дружественное имя и имя). Вот как это выглядит: http://i.stack.imgur.com/Rg1dC.png < / а>

Как только поле «Дружественное имя» заполняется, добавляю пустую строку. Я использую событие LostKeyboardFocus, чтобы проверить, нужно ли добавлять пустой MyDataItem, и обновить свойство IEnumerable ‹MyDataItem>.

Проблема: я теряю фокус при добавлении элемента. Поэтому, если я перехожу от понятного имени к имени и добавляю новую строку, фокус теряется с имени. Как я могу это решить?

ИЗМЕНИТЬ: под кодом, чтобы показать мою проблему. Я хочу иметь возможность переходить от ячейки к ячейке. Когда обе ячейки строки остаются пустыми, я хочу удалить эту строку. В конце я хочу иметь пустую строку (обе ячейки пусты). На этом этапе код работает, но теряет фокус, если вы используете вкладку. А работа со списком приводит к тому, что TAB не работает для перехода к следующему элементу в списке.

XAML:

<Window x:Class="Focus.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Focus"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d" 
    d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=True}"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="DataTemplate1">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="5"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox LostKeyboardFocus="TextBox_LostKeyboardFocus">
                <TextBox.Text>
                    <Binding Path="FriendlyName" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>
            </TextBox>
            <TextBox Grid.Column="2" LostKeyboardFocus="TextBox_LostKeyboardFocus">
                <TextBox.Text>
                    <Binding Path="Name" UpdateSourceTrigger="PropertyChanged"/>
                </TextBox.Text>
            </TextBox>
        </Grid>
    </DataTemplate>

</Window.Resources>
<Grid>
    <ListBox Margin="10" ItemsSource="{Binding OrderedItems}" ItemTemplate="{DynamicResource DataTemplate1}" HorizontalContentAlignment="Stretch">

    </ListBox>
</Grid>

Code behind:

using System.Windows;
using System.Windows.Input;

namespace Focus
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }

        private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            MainViewModel vm = this.DataContext as MainViewModel;
            vm.CheckToAddEmptyItem();
        }        
    }
}

ViewModel

using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Focus
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private List<MyItem> _myItems = new List<MyItem>();
        public IEnumerable<MyItem> OrderedItems
        {
            get { return _myItems.OrderBy(i => i.IsEmpty); }
        }

        internal void CheckToAddEmptyItem()
        {
            int count = _myItems.Count(i => i.IsEmpty);

            if (count == 0)
            {
                _myItems.Add(new MyItem());

                if (null != PropertyChanged)
                    PropertyChanged(this, new PropertyChangedEventArgs("OrderedItems"));
            }
            else if (count > 1)
            {
                var items = _myItems.Where(i => i.IsEmpty).Skip(1).ToArray();

                foreach (MyItem item in items)
                    _myItems.Remove(item);

                if (null != PropertyChanged)
                    PropertyChanged(this, new PropertyChangedEventArgs("OrderedItems"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public MainViewModel()
        {
            for(int i=1; i <= 5; ++i)
            {
                _myItems.Add(new MyItem() { FriendlyName = "Item #" + i, Name = "ITEM" + i });
            }

            if (null != PropertyChanged)
                PropertyChanged(this, new PropertyChangedEventArgs("OrderedItems"));

            CheckToAddEmptyItem();
        }
    }
}

Класс MyItem:

using System.ComponentModel;

namespace Focus
{
    public class MyItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _name = string.Empty;    
        public string Name
        {
            get { return _name; }
            set
            {
                if (value != _name)
                {
                    _name = value;
                    if (null != PropertyChanged)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Name"));
                        PropertyChanged(this, new PropertyChangedEventArgs("IsEmpty"));
                    }
                }
            }
        }

        private string _friendlyName = string.Empty;
        public string FriendlyName
        {
            get { return _friendlyName; }
            set
            {
                if (value != _friendlyName)
                {
                    _friendlyName = value;
                    if (null != PropertyChanged)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("FriendlyName"));
                        PropertyChanged(this, new PropertyChangedEventArgs("IsEmpty"));
                    }
                }
            }
        }

        public bool IsEmpty
        {
            get { return string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(FriendlyName); }
        }
    }
}

person jim    schedule 21.01.2014    source источник
comment
Вам нужно найти TextBox в своем ItemTemplate после добавления нового элемента и сфокусировать его. Посмотрите этот ответ, чтобы найти свой элемент управления в шаблоне: Найти контроль в ItemTenplate   -  person Valera Scherbakov    schedule 21.01.2014
comment
Я буду смотреть в него. Спасибо за ответ.   -  person jim    schedule 21.01.2014


Ответы (1)


ItemsControl не так удобен в соответствии с вашими потребностями, поскольку нет свойств для получения определенного выбранного элемента. Вместо этого попробуйте использовать Listbox, поскольку он предоставляет такие свойства, как SelectedItem, SelectedIndex и т. Д. Используя эти свойства, вы можете получить дочерний элемент управления с любым значением индекса.

PS: Я мог бы уточнить свой ответ, если вы хотите использовать alistbox и получить дочерние элементы.

person A.K.    schedule 21.01.2014
comment
Спасибо за ответ, но я не понимаю, как использование списка поможет мне потерять фокус. - person jim; 21.01.2014