将项目添加到Itemscontrol时,如何防止DataTemplate文本框失去焦点?

时间:2014-01-21 09:36:57

标签: wpf focus itemscontrol wpf-4.0

我有一个ItemsControl,ItemsSource绑定到IEnumerable< MyDataItem>。

ItemTemplate包含两个文本框。 (友好的名字和名字)。这就是它的样子:http://i.stack.imgur.com/Rg1dC.png

填写“友好名称”字段后,我会添加一个空行。我使用LostKeyboardFocus事件来检查是否添加一个空的“MyDataItem”并刷新IEnumerable< MyDataItem>属性。

问题:添加项目时我失去了焦点。因此,如果我从友好名称到名称并且添加了新行,则焦点将从名称中丢失。我该如何解决这个问题?

编辑:在某些代码下面显示我的问题。我想能够从一个细胞到另一个细胞进行TAB。当一行的两个单元格都留空时,我想删除该行。最后我想要一个空行(两个单元格都为空)。此时代码可以正常工作,但如果使用制表符则会失去焦点。使用列表框会使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>

代码背后:

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

1 个答案:

答案 0 :(得分:0)

根据您的需要,ItemsControl并不友好,因为没有属性可以获得特定的选定项目。尝试使用Listbox相反,因为它公开了SelectedItem,SelectedIndex等属性,使用这些属性可以获得任何索引值的子控件。

PS:如果您希望使用alistbox并获取子元素,我可以详细说明我的答案。