Dans mon application WPF, j'ai une base de données TextBox
et une base de données ItemsControl
. Le contenu du ItemsControl
est déterminé par le contenu du TextBox
. Je veux être en mesure de taper une valeur dans le TextBox
, appuyez sur l'onglet et entrez le premier élément dans le ItemsControl
(créé à partir de la valeur dans le TextBox
). Le problème que j'ai est que l'action de tabulation est évaluée avant que WPF crée les éléments de modèle dans le ItemsControl
. Le code suivant illustre ce problème:WPF Tab Into Databound ItemsControl
<Window x:Class="BindingExample.Window1" x:Name="SelfControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:BindingExample" Title="Window1" Height="300" Width="400">
<Window.Resources>
<DataTemplate DataType="{x:Type loc:ChildClass}">
<TextBox Text="{Binding Value}" />
</DataTemplate>
</Window.Resources>
<StackPanel DataContext="{Binding ElementName=SelfControl}" Focusable="False">
<Label Content="Options: A, B, C" />
<TextBox Text="{Binding Object.Value}" />
<ItemsControl Margin="16,0,0,0" ItemsSource="{Binding Object.Children}" Focusable="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<TextBox Text="Box2" />
</StackPanel>
</Window>
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
namespace BindingExample
{
public partial class Window1
{
public static readonly DependencyProperty ObjectProperty = DependencyProperty.Register("Object", typeof(ParentClass), typeof(Window1));
public ParentClass Object
{
get { return GetValue(ObjectProperty) as ParentClass; }
set { SetValue(ObjectProperty, value); }
}
public Window1()
{
InitializeComponent();
Object = new ParentClass();
}
}
public class ParentClass : INotifyPropertyChanged
{
private string value;
public string Value
{
get { return value; }
set { this.value = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Children")); }
}
public IEnumerable<ChildClass> Children
{
get
{
switch (Value.ToUpper())
{
case "A": return new ChildClass[] { "A-1", "A-2", "A-2" };
case "B": return new ChildClass[] { "B-1", "B-2", "B-3" };
case "C": return new ChildClass[] { "C-1", "C-2", "C-2" };
default: return new ChildClass[] { "Unknown" };
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class ChildClass
{
public string Value { get; set; }
public static implicit operator ChildClass(string value) { return new ChildClass { Value = value }; }
}
}
Dans ce code, je voudrais saisir « A » dans la première TextBox
, onglet de presse, et ont le changement de mise au point à l'enfant TextBox
avec le texte "A-1". Au lieu de cela, la mise au point passe à la zone de texte avec le texte "Box2". Comment puis-je atteindre le comportement que je recherche ici?
Note: Comme Julien Poulin a souligné, il est possible de faire ce travail en mettant l'UpdateSourceTrigger
sur le TextBox
-PropertyChanged
. Cela ne fonctionne cependant que si la liaison "en cours de frappe" est acceptable. Dans mon cas, je voudrais également faire le jeu de la valeur et l'onglet avec une seule touche. Existe-t-il un moyen de forcer le ItemsControl à créer ses éléments basés sur des modèles à la demande?
Cela fonctionne. Idéalement, cependant, j'aimerais que la liaison se produise lorsque le contrôle perd le focus, pas pendant que l'utilisateur tape. –
Je ne pense pas qu'il sera possible de définir automatiquement le focus sur le TextBox à l'intérieur de ItemsControl car ils ne sont pas encore créés lorsque votre 1er TextBox perd le focus. Vous pourriez écrire du code pour mettre l'accent là où il devrait appartenir, mais il semblerait que ce soit vraiment désordonné. –