Você pode se tornar uma abordagem XAML pura criando um comportamento anexado .
Algo assim:
public static class InputBindingsManager
{
public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
"UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));
static InputBindingsManager()
{
}
public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
{
dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
}
public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
{
return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
}
private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = dp as UIElement;
if (element == null)
{
return;
}
if (e.OldValue != null)
{
element.PreviewKeyDown -= HandlePreviewKeyDown;
}
if (e.NewValue != null)
{
element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
}
}
static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
DoUpdateSource(e.Source);
}
}
static void DoUpdateSource(object source)
{
DependencyProperty property =
GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);
if (property == null)
{
return;
}
UIElement elt = source as UIElement;
if (elt == null)
{
return;
}
BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);
if (binding != null)
{
binding.UpdateSource();
}
}
}
Em seguida, em seu XAML, você define a InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
propriedade para aquela que deseja atualizar quando a Entertecla é pressionada. Como isso
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(Você só precisa ter certeza de incluir uma referência xmlns clr-namespace para "b" no elemento raiz de seu arquivo XAML apontando para qualquer namespace em que você colocou o InputBindingsManager).
UpdatePropertySourceWhenEnterPressed
mudanças de um valor válido para um valor válido diferente, você está cancelando e re-assinando oPreviewKeyDown
evento desnecessariamente. Em vez disso, tudo que você precisa é verificar se oe.NewValue
énull
ou não. Se nãonull
, então se inscreva; caso contrário, senull
, cancele a inscrição.Foi assim que resolvi esse problema. Criei um manipulador de eventos especial que foi inserido no código por trás de:
Então, acabei de adicionar isso como um manipulador de eventos KeyUp no XAML:
O manipulador de eventos usa sua
sender
referência para fazer com que sua própria vinculação seja atualizada. Como o manipulador de eventos é independente, ele deve funcionar em um DataTemplate complexo. Esse manipulador de eventos agora pode ser adicionado a todas as caixas de texto que precisam desse recurso.fonte
KeyBinding
no XAML para disparar esse método porque minha IU tem um controle "Padrão" que captura a tecla enter. Você precisa capturá-lo dentro deste TextBox para impedir que ele se propague na árvore da interface do usuário para o controle "Padrão".Não acredito que haja uma maneira "puro XAML" de fazer o que você está descrevendo. Você pode configurar uma vinculação para que seja atualizada sempre que o texto em um TextBox mudar (em vez de quando o TextBox perder o foco) definindo a propriedade UpdateSourceTrigger , como este:
Se você definir UpdateSourceTrigger como "Explicit" e, em seguida, manipular o evento PreviewKeyDown do TextBox (procurando a tecla Enter), poderá obter o que deseja, mas exigiria code-behind. Talvez algum tipo de propriedade anexada (semelhante à minha propriedade EnterKeyTraversal ) funcione para você.
fonte
Você pode criar facilmente seu próprio controle herdado de TextBox e reutilizá-lo em todo o projeto.
Algo semelhante a isso deve funcionar:
Pode haver uma maneira de contornar esta etapa, mas caso contrário, você deve vincular assim (usando Explícito):
fonte
Se você combinar as soluções Ben e ausadmin, terminará com uma solução muito amigável para MVVM:
... o que significa que você está passando o
TextBox
próprio como parâmetro para oCommand
.Isso faz com que você
Command
fique assim (se estiver usando umaDelegateCommand
implementação de estilo em sua VM):Essa
Command
implementação pode ser usada para qualquerTextBox
e, melhor de tudo, nenhum código no code-behind, embora você possa querer colocá-lo em sua própria classe para que não haja dependênciasSystem.Windows.Controls
em sua VM. Depende de quão rígidas são as suas diretrizes de código.fonte
Aqui está uma abordagem que para mim parece bastante direta e mais fácil do que adicionar um AttachedBehaviour (que também é uma solução válida). Usamos o UpdateSourceTrigger padrão (LostFocus para TextBox) e, em seguida, adicionamos um InputBinding à tecla Enter, vinculado a um comando.
O xaml é o seguinte
Então os métodos de comando são
E o TextBox está vinculado à propriedade
Até agora, isso parece funcionar bem e captura o evento Enter Key no TextBox.
fonte
Esta não é uma resposta à pergunta original, mas sim uma extensão da resposta aceita por @Samuel Jack. Fiz o seguinte em meu próprio requerimento e fiquei maravilhado com a elegância da solução de Samuel. É muito limpo e muito reutilizável, pois pode ser usado em qualquer controle, não apenas no
TextBox
. Achei que isso deveria ser compartilhado com a comunidade.Se você tiver uma janela com mil
TextBoxes
que exigem a atualização da Binding Source no Enter, você pode anexar esse comportamento a todos eles incluindo o XAML abaixo em seu emWindow
Resources
vez de anexá-lo a cada TextBox. Primeiro você deve implementar o comportamento anexado de acordo com a postagem de Samuel, é claro.Você sempre pode limitar o escopo, se necessário, colocando o estilo nos recursos de um dos elementos filhos da janela (ou seja, a
Grid
) que contém as TextBoxes de destino.fonte
Caso você esteja usando MultiBinding com sua TextBox, você precisa usar o
BindingOperations.GetMultiBindingExpression
método em vez deBindingOperations.GetBindingExpression
.fonte
Isso funciona para mim:
fonte
Respondi aqui com bastante elegância, usando comportamentos vinculados, meu método preferido para quase tudo.
WPF como fazer a caixa de texto perder o foco após pressionar Enter
fonte
Pessoalmente, acho que ter uma extensão de marcação é uma abordagem mais limpa.
fonte
Uma solução diferente (sem usar xaml, mas ainda bem limpa, eu acho).
fonte