Eu tenho um TextBox
e um Button
na minha opinião.
Agora, estou verificando uma condição ao clicar no botão e, se ela for falsa, exibindo a mensagem para o usuário e, em seguida, preciso definir o cursor no TextBox
controle.
if (companyref == null)
{
var cs = new Lipper.Nelson.AdminClient.Main.Views.ContactPanels.CompanyAssociation();
MessageBox.Show("Company does not exist.", "Error", MessageBoxButton.OK,
MessageBoxImage.Exclamation);
cs.txtCompanyID.Focusable = true;
System.Windows.Input.Keyboard.Focus(cs.txtCompanyID);
}
O código acima está no ViewModel.
O CompanyAssociation
é o nome da visualização.
Mas o cursor não está sendo definido no TextBox
.
O xaml é:
<igEditors:XamTextEditor Name="txtCompanyID"
KeyDown="xamTextEditorAllowOnlyNumeric_KeyDown"
ValueChanged="txtCompanyID_ValueChanged"
Text="{Binding Company.CompanyId,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Width="{Binding ActualWidth, ElementName=border}"
Grid.Column="1" Grid.Row="0"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
Margin="0,5,0,0"
IsEnabled="{Binding Path=IsEditable}"/>
<Button Template="{StaticResource buttonTemp1}"
Command="{Binding ContactCommand}"
CommandParameter="searchCompany"
Content="Search"
Width="80"
Grid.Row="0" Grid.Column="2"
VerticalAlignment="Top"
Margin="0"
HorizontalAlignment="Left"
IsEnabled="{Binding Path=IsEditable}"/>
Respostas:
Deixe-me responder à sua pergunta em três partes.
Gostaria de saber o que é "cs.txtCompanyID" no seu exemplo? É um controle TextBox? Se sim, então você está no caminho errado. De um modo geral, não é uma boa ideia ter qualquer referência à interface do usuário no seu ViewModel. Você pode perguntar "Por quê?" mas essa é outra pergunta para postar no Stackoverflow :).
A melhor maneira de rastrear problemas com o Focus é ... depurando o código-fonte .Net. Sem brincadeiras. Isso me salvou muito tempo várias vezes. Para habilitar a depuração do código-fonte .net, consulte o blog de Shawn Bruke .
Finalmente, a abordagem geral que eu uso para definir o foco do ViewModel é Attached Properties. Escrevi uma propriedade anexada muito simples, que pode ser definida em qualquer UIElement. E pode ser associado à propriedade "IsFocused" do ViewModel, por exemplo. Aqui está:
Agora, no seu View (em XAML), você pode vincular essa propriedade ao seu ViewModel:
Espero que isto ajude :). Se não se referir à resposta # 2.
Felicidades.
fonte
Keyboard.Focus(uie);
de seuOnIsFocusedPropertyChanged
evento, se você quiser que o seu controle para receber o foco do teclado, bem como foco lógico...if ((bool)e.NewValue && uie.Dispatcher != null) { uie.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => uie.Focus())); // invoke behaves nicer, if e.g. you have some additional handler attached to 'GotFocus' of UIE. uie.SetValue(IsFocusedProperty, false); // reset bound value if possible, to allow setting again ...
Às vezes, tenho que redefinir o 'IsFocused' para false no ViewModel, se quiser definir o foco várias vezes. Mas então funciona, onde outros métodos falharam.public bool IsFocused { get { return _isFocused; } set { if (_isFocused == value) { _isFocused = false; OnPropertyChanged(); } _isFocused = value; OnPropertyChanged(); } }
Sei que essa pergunta já foi respondida mil vezes até agora, mas fiz algumas edições na contribuição de Anvaka que, em minha opinião, ajudará outras pessoas que tiveram problemas semelhantes.
Em primeiro lugar, alterei a propriedade anexada acima da seguinte forma:
Meu motivo para adicionar as referências de visibilidade foram as guias. Aparentemente, se você usou a propriedade anexada em qualquer outra guia fora da guia inicialmente visível, a propriedade anexada não funcionou até você focar o controle manualmente.
O outro obstáculo era criar uma maneira mais elegante de redefinir a propriedade subjacente para false quando ela perdia o foco. Foi aí que entraram os eventos de foco perdido.
Se houver uma maneira melhor de lidar com o problema de visibilidade, entre em contato.
Nota: Agradecemos a Apfelkuacha pela sugestão de colocar o BindsTwoWayByDefault no DependencyProperty. Eu tinha feito isso há muito tempo no meu próprio código, mas nunca atualizei este post. O Mode = TwoWay não é mais necessário no código WPF devido a essa alteração.
fonte
fe.Dispatcher.BeginInvoke(new Action(() => { fe.Focus(); }), DispatcherPriority.Loaded);
que é atualizado após o carregamento. Mais informações aqui: telerik.com/forums/isfocused-property#OXgFYZFOg0WZ2rxidln61QEu acho que a melhor maneira é manter limpo o princípio do MVVM, então basicamente você deve usar a classe Messenger fornecida com o MVVM Light e aqui está como usá-lo:
no seu viewmodel (exampleViewModel.cs): escreva o seguinte
agora no seu View.cs (não no XAML, no view.xaml.cs) escreva o seguinte no construtor
esse método funciona bem e com menos código e mantendo os padrões MVVM
fonte
Nenhuma delas funcionou exatamente para mim, mas para o benefício de outras pessoas, foi isso que acabei escrevendo com base em alguns dos códigos já fornecidos aqui.
O uso seria o seguinte:
E a implementação seria a seguinte:
fonte
Esse é um encadeamento antigo, mas não parece haver uma resposta com código que resolva os problemas da resposta aceita pelo Anavanka: não funcionará se você definir a propriedade no viewmodel como false ou se você configurar sua propriedade como true, o usuário clica manualmente em outra coisa e você a define como true novamente. Também não consegui que a solução da Zamotic funcionasse de maneira confiável nesses casos.
Reunir algumas das discussões acima fornece o código abaixo, que aborda esses problemas, eu acho:
Dito isto, isso ainda é complexo para algo que pode ser feito em uma linha no codebehind, e o CoerceValue não deve ser usado dessa maneira, então talvez o codebehind seja o caminho a seguir.
fonte
No meu caso, o FocusExtension não funcionou até eu alterar o método OnIsFocusedPropertyChanged. O original estava trabalhando apenas na depuração quando um ponto de interrupção interrompeu o processo. Em tempo de execução, o processo é muito rápido e nada aconteceu. Com esta pequena modificação e a ajuda do nosso amigo Task, isso está funcionando bem nos dois cenários.
fonte
O problema é que, quando o IsUserNameFocused estiver definido como true, ele nunca será falso. Isso resolve o problema, manipulando GotFocus e LostFocus para o FrameworkElement.
Eu estava tendo problemas com a formatação do código fonte, então aqui está um link
fonte
O código brilhante Anvakas é para aplicativos da área de trabalho do Windows. Se você é como eu e precisava da mesma solução para aplicativos da Windows Store, esse código pode ser útil:
fonte
Para aqueles que tentaram usar a solução da Anvaka acima, eu estava tendo problemas com a ligação funcionando apenas pela primeira vez, pois o lostfocus não atualizaria a propriedade como false. Você pode definir manualmente a propriedade como false e true sempre, mas uma solução melhor pode ser fazer algo assim em sua propriedade:
Dessa forma, você só precisa configurá-lo como verdadeiro, e ele terá foco.
fonte
Eu uso o WPF / Caliburn Micro e descobri que "dfaivre" criou uma solução geral e viável aqui: http://caliburnmicro.codeplex.com/discussions/222892
fonte
Encontrei a solução editando o código conforme a seguir. Não há necessidade de definir a propriedade Binding primeiro False e True.
fonte
Para o Silverlight:
LoginViewModel.cs:
Login.xaml:
OU
Para definir o foco, basta fazê-lo no código:
Lembre-se de que este plug-in faz parte de uma página html; portanto, outros controles na página podem ter o foco
fonte
Você pode usar o padrão de design do ViewCommand . Ele descreve um método para o padrão de design MVVM para controlar uma View de um ViewModel com comandos.
Eu o implementei com base na sugestão do rei A.Majid de usar a classe MVVM Light Messenger. A classe ViewCommandManager manipula a chamada de comandos nas visualizações conectadas. É basicamente a outra direção dos comandos regulares, para esses casos em que um ViewModel precisa executar alguma ação em seu View. Ele usa reflexão como comandos ligados a dados e WeakReferences para evitar vazamentos de memória.
http://dev.unclassified.de/source/viewcommand (também publicado no CodeProject)
fonte
Parece que ninguém incluiu a etapa final para facilitar a atualização de atributos por meio de variáveis ligadas. Aqui está o que eu criei. Deixe-me saber se existe uma maneira melhor de fazer isso.
XAML
ViewModel
fonte
Primeiramente, gostaria de agradecer à Avanka por me ajudar a resolver meu problema de foco. No entanto, há um erro no código que ele postou, ou seja, na linha: if (e.OldValue == null)
O problema que tive foi que, se você clicar pela primeira vez na visualização e focar o controle, o e.oldValue não será mais nulo. Então, quando você define a variável para focar o controle pela primeira vez, isso resulta nos manipuladores de foco perdido e foco automático não sendo definidos. Minha solução para isso foi a seguinte:
fonte
Apenas faça o seguinte:
fonte
Após implementar a resposta aceita, deparei-me com um problema que, ao navegar pelas visualizações com o Prism, o TextBox ainda não ficava em foco. Uma pequena alteração no manipulador PropertyChanged resolveu
fonte
Uma abordagem alternativa baseada na resposta @Sheridan aqui
No seu modelo de visualização, configure sua encadernação da maneira usual e defina SomeTextIsFocused como true para definir o foco na sua caixa de texto
fonte
Encontrei Crucial a solução da para o problema do IsVisible muito útil. Não resolveu completamente o meu problema, mas algum código extra seguindo o mesmo padrão para o padrão IsEnabled.
Ao método IsFocusedChanged, adicionei:
E aqui está o manipulador:
fonte
fonte
fonte