Saya memiliki TextBox
dan Button
dalam pandangan saya.
Sekarang saya memeriksa suatu kondisi pada tombol klik dan jika kondisi ternyata salah, menampilkan pesan kepada pengguna, dan kemudian saya harus mengatur kursor ke TextBox
kontrol.
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);
}
Kode di atas ada di dalam ViewModel.
The CompanyAssociation
adalah nama tampilan.
Tetapi kursor tidak diatur dalam TextBox
.
XAML adalah:
<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}"/>
Jawaban:
Biarkan saya menjawab pertanyaan Anda dalam tiga bagian.
Saya bertanya-tanya apa itu "cs.txtCompanyID" dalam contoh Anda? Apakah ini kontrol TextBox? Jika ya, berarti Anda berada di jalan yang salah. Secara umum itu bukan ide yang baik untuk memiliki referensi ke UI di ViewModel Anda. Anda bisa bertanya, "Kenapa?" tapi ini pertanyaan lain untuk dikirim di Stackoverflow :).
Cara terbaik untuk melacak masalah dengan Fokus adalah ... men-debug kode sumber .Net. Tidak bercanda. Ini menyelamatkan saya banyak waktu berkali-kali. Untuk mengaktifkan debugging kode sumber .net, lihat blog Shawn Bruke .
Akhirnya, pendekatan umum yang saya gunakan untuk mengatur fokus dari ViewModel adalah Properti Terlampir. Saya menulis properti terlampir yang sangat sederhana, yang dapat diset pada UIElement apa pun. Dan itu dapat diikat ke properti ViewModel "IsFocused" misalnya. Ini dia:
Sekarang di View Anda (dalam XAML) Anda dapat mengikat properti ini ke ViewModel Anda:
Semoga ini membantu :). Jika tidak merujuk ke jawaban # 2.
Bersulang.
sumber
Keyboard.Focus(uie);
dariOnIsFocusedPropertyChanged
acara Anda jika Anda ingin kontrol Anda menerima Fokus Keyboard serta Fokus Logis...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 ...
Kadang-kadang saya bahkan harus mengatur ulang 'IsFocused' menjadi false di ViewModel, jika saya ingin mengatur fokus beberapa kali. Tapi kemudian berhasil, di mana beberapa metode lain gagal.public bool IsFocused { get { return _isFocused; } set { if (_isFocused == value) { _isFocused = false; OnPropertyChanged(); } _isFocused = value; OnPropertyChanged(); } }
Saya tahu pertanyaan ini telah dijawab ribuan kali sekarang, tetapi saya mengedit kontribusi Anvaka yang saya pikir akan membantu orang lain yang memiliki masalah serupa yang saya miliki.
Pertama, saya mengubah Properti Terlampir di atas seperti:
Alasan saya untuk menambahkan referensi visibilitas adalah tab. Tampaknya jika Anda menggunakan properti terlampir pada tab lain di luar tab yang awalnya terlihat, properti terlampir tidak berfungsi sampai Anda memfokuskan kontrol secara manual.
Kendala lain adalah menciptakan cara yang lebih elegan untuk mengatur ulang properti yang mendasarinya menjadi false ketika kehilangan fokus. Di situlah peristiwa fokus yang hilang masuk.
Jika ada cara yang lebih baik untuk menangani masalah visibilitas, beri tahu saya.
Catatan: Terima kasih kepada Apfelkuacha untuk saran menempatkan BindsTwoWayByDefault di DependencyProperty. Saya sudah melakukannya sejak lama di kode saya sendiri, tetapi tidak pernah memperbarui posting ini. Mode = TwoWay tidak lagi diperlukan dalam kode WPF karena perubahan ini.
sumber
fe.Dispatcher.BeginInvoke(new Action(() => { fe.Focus(); }), DispatcherPriority.Loaded);
itu diperbarui setelah dimuat. Info lebih lanjut di sini: telerik.com/forums/isfocused-property#OXgFYZFOg0WZ2rxidln61QSaya pikir cara terbaik adalah menjaga prinsip MVVM bersih, jadi pada dasarnya Anda harus menggunakan Kelas Messenger yang disediakan dengan MVVM Light dan di sini adalah bagaimana menggunakannya:
di viewmodel Anda (exampleViewModel.cs): tulis berikut ini
sekarang di View.cs Anda (bukan XAML, view.xaml.cs) tulis yang berikut di konstruktor
Metode itu berjalan dengan baik dan dengan kode yang lebih sedikit dan mempertahankan standar MVVM
sumber
Tak satu pun dari ini bekerja untuk saya persis, tetapi untuk kepentingan orang lain, inilah yang akhirnya saya tulis berdasarkan beberapa kode yang sudah disediakan di sini.
Penggunaannya adalah sebagai berikut:
Dan implementasinya adalah sebagai berikut:
sumber
Ini adalah utas lama, tetapi sepertinya tidak ada jawaban dengan kode yang mengatasi masalah dengan jawaban yang diterima Anavanka: tidak berfungsi jika Anda menyetel properti di viewmodel menjadi false, atau jika Anda menyetel properti Anda ke benar, pengguna secara manual mengklik sesuatu yang lain, dan kemudian Anda mengaturnya menjadi benar lagi. Saya juga tidak bisa mendapatkan solusi Zamotic untuk bekerja dengan andal dalam kasus-kasus ini.
Menyatukan beberapa diskusi di atas memberi saya kode di bawah ini yang menangani masalah ini, saya pikir:
Karena itu, ini masih kompleks untuk sesuatu yang dapat dilakukan dalam satu baris dalam codebehind, dan CoerceValue tidak benar-benar dimaksudkan untuk digunakan dengan cara ini, jadi mungkin codebehind adalah cara untuk pergi.
sumber
Dalam kasus saya, FocusExtension tidak berfungsi sampai saya mengubah metode OnIsFocusedPropertyChanged. Yang asli hanya berfungsi di debug ketika break point menghentikan proses. Saat runtime, prosesnya terlalu cepat dan tidak ada yang terjadi. Dengan sedikit modifikasi ini dan bantuan Tugas teman kita, ini berfungsi dengan baik di kedua skenario.
sumber
Masalahnya adalah begitu IsUserNameFocused disetel ke true, itu tidak akan pernah salah. Ini menyelesaikannya dengan menangani GotFocus dan LostFocus untuk FrameworkElement.
Saya mengalami masalah dengan pemformatan kode sumber jadi di sini ada tautan
sumber
Kode brilian Anvakas adalah untuk aplikasi Windows Desktop. Jika Anda seperti saya dan membutuhkan solusi yang sama untuk aplikasi Windows Store, kode ini mungkin berguna:
sumber
Bagi mereka yang mencoba menggunakan solusi Anvaka di atas, saya mengalami masalah dengan pengikatan hanya berfungsi pertama kali, karena kehilanganfokus tidak akan memperbarui properti ke false. Anda dapat secara manual mengatur properti menjadi false dan kemudian benar setiap kali, tetapi solusi yang lebih baik bisa dengan melakukan sesuatu seperti ini di properti Anda:
Dengan cara ini Anda hanya perlu mengaturnya menjadi benar, dan itu akan mendapatkan fokus.
sumber
Saya menggunakan WPF / Caliburn Micro dan menemukan bahwa "dfaivre" telah membuat solusi umum dan dapat diterapkan di sini: http://caliburnmicro.codeplex.com/discussions/222892
sumber
Saya telah menemukan solusi dengan mengedit kode sebagai berikut. Tidak perlu mengatur properti Binding terlebih dahulu False lalu True.
sumber
Untuk Silverlight:
LoginViewModel.cs:
Login.xaml:
ATAU
Untuk mengatur fokus, lakukan saja dalam kode:
Ingat bahwa plugin ini adalah bagian dari halaman html, jadi kontrol lain di halaman tersebut mungkin memiliki fokus
sumber
Anda bisa menggunakan pola desain ViewCommand . Ini menjelaskan metode untuk pola desain MVVM untuk mengontrol tampilan dari ViewModel dengan perintah.
Saya sudah mengimplementasikannya berdasarkan saran Raja A.Majid untuk menggunakan kelas MVVM Light Messenger. Kelas ViewCommandManager menangani perintah pemanggilan dalam tampilan yang terhubung. Ini pada dasarnya adalah arah lain dari Perintah reguler, untuk kasus-kasus ini ketika ViewModel perlu melakukan beberapa tindakan dalam Tampilannya. Ini menggunakan refleksi seperti perintah terikat data dan Referensi Lemah untuk menghindari kebocoran memori.
http://dev.unclassified.de/source/viewcommand (juga dipublikasikan di CodeProject)
sumber
Sepertinya tidak ada yang memasukkan langkah terakhir untuk memudahkan memperbarui atribut melalui variabel terikat. Inilah yang saya pikirkan. Beri tahu saya jika ada cara yang lebih baik untuk melakukan ini.
XAML
ViewModel
sumber
Pertama-tama saya ingin mengucapkan terima kasih kepada Avanka karena telah membantu saya memecahkan masalah fokus saya. Namun ada bug dalam kode yang dia posting, yaitu di baris: if (e.OldValue == null)
Masalah yang saya miliki adalah bahwa jika Anda pertama kali mengklik pada tampilan Anda dan memfokuskan kontrol, e.oldValue tidak lagi nol. Kemudian ketika Anda mengatur variabel untuk memfokuskan kontrol untuk pertama kalinya, ini menghasilkan fokus yang hilang dan penangan fokus yang tidak ditetapkan. Solusi saya untuk ini adalah sebagai berikut:
sumber
Lakukan saja ini:
sumber
Setelah menerapkan jawaban yang diterima, saya menemukan masalah yang saat menavigasi tampilan dengan Prism TextBox masih tidak akan mendapatkan fokus. Perubahan kecil ke penangan PropertyChanged menyelesaikannya
sumber
Pendekatan alternatif berdasarkan jawaban @Sheridan di sini
Dalam model tampilan Anda, atur ikatan Anda dengan cara biasa dan kemudian atur SomeTextIsFocused menjadi true untuk mengatur fokus pada kotak teks Anda
sumber
Saya menemukan solusi Krusial untuk masalah IsVisible sangat berguna. Itu tidak sepenuhnya menyelesaikan masalah saya, tetapi beberapa kode tambahan mengikuti pola yang sama untuk pola IsEnabled.
Ke metode IsFocusedChanged saya menambahkan:
Dan ini dia:
sumber
sumber
sumber