Bagaimana cara menonaktifkan pilihan di ListBox?
Bagaimana cara menonaktifkan pilihan di ListBox?
Jawaban:
ItemsControl
Kecuali Anda membutuhkan aspek lain dari itu ListBox
, Anda dapat menggunakannya ItemsControl
sebagai gantinya. Ini menempatkan item dalam ItemsPanel
dan tidak memiliki konsep seleksi.
<ItemsControl ItemsSource="{Binding MyItems}" />
Secara default, ItemsControl
tidak mendukung virtualisasi elemen turunannya. Jika Anda memiliki banyak item, virtualisasi dapat mengurangi penggunaan memori dan meningkatkan kinerja, dalam hal ini Anda dapat menggunakan pendekatan 2 dan gaya ListBox
, atau menambahkan virtualisasi ke AndaItemsControl
.
ListBox
Atau, cukup gaya ListBox sehingga seleksi tidak terlihat.
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Style.Resources>
<!-- SelectedItem with focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent" />
<!-- SelectedItem without focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<!-- SelectedItem text foreground -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
Color="Black" />
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</ListBox.Resources>
ItemsControl
akan sepenuhnya menghilangkan konsep seleksi apa pun.
Saya menemukan solusi yang sangat sederhana dan lurus ke depan bekerja untuk saya, saya harap itu akan berhasil juga untuk Anda
<ListBox ItemsSource="{Items}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Focusable = "False"
!
<Setter Property="IsHitTestVisible" Value="False" />
Anda dapat beralih menggunakan ItemsControl
bukan ListBox
. An ItemsControl
tidak memiliki konsep seleksi, jadi tidak ada yang perlu dimatikan.
ItemTemplate
.
Opsi lain yang layak dipertimbangkan adalah menonaktifkan ListBoxItems. Ini dapat dilakukan dengan mengatur ItemContainerStyle seperti yang ditunjukkan pada cuplikan berikut.
<ListBox ItemsSource="{Binding YourCollection}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsEnabled" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Jika Anda tidak ingin teks menjadi abu-abu, Anda dapat menentukan warna yang dinonaktifkan dengan menambahkan kuas ke sumber daya gaya dengan tombol berikut: {x: Static SystemColors.GrayTextBrushKey}. Solusi lain adalah menimpa templat kontrol ListBoxItem.
Ini juga akan berfungsi, jika saya harus menggunakan listbox alih-alih itemscontrol, tetapi saya hanya menampilkan item yang tidak boleh dipilih, saya menggunakan:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
Jawaban yang cukup bagus di sini, tetapi saya mencari sesuatu yang sedikit berbeda: Saya ingin seleksi, tetapi tidak ingin ditampilkan (atau ditampilkan dalam masalah yang berbeda).
Solusi di atas tidak bekerja untuk saya (sepenuhnya), jadi saya melakukan sesuatu yang lain: Saya menggunakan gaya baru untuk listbox saya, yang sepenuhnya mengubah template:
<Style x:Key="PlainListBoxStyle" TargetType="ListBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Dimulai dengan itu, Anda dapat dengan mudah menambahkan sorotan pilihan Anda sendiri, atau membiarkannya seperti itu jika Anda tidak menginginkannya sama sekali.
Sementara jawaban @Drew Noakes adalah solusi cepat untuk sebagian besar kasus, ada sedikit cacat yang datang dengan mengatur x: sikat statis.
Ketika Anda mengatur x: sikat statis seperti yang disarankan, semua anak-anak kontrol dalam item kotak daftar akan mewarisi gaya ini.
Itu berarti bahwa, sementara ini akan berfungsi untuk menonaktifkan penyorotan item kotak daftar, itu dapat mengakibatkan efek yang tidak diinginkan untuk kontrol anak.
Sebagai contoh, jika Anda memiliki ComboBox di dalam ListBoxItem Anda, itu akan menonaktifkan mouse selama penyorotan dalam ComboBox.
Alih-alih, pertimbangkan untuk mengatur VisualStates untuk acara yang Dipilih, Tidak Terpilih, dan MouseOver sebagaimana dicakup dalam solusi yang disebutkan dalam untaian stackoverflow ini: Hapus Sorotan Kontrol Dari ListBoxItem tetapi bukan kontrol anak-anak .
-Frinny
Saya mengusulkan solusi lain. Cukup templat ulang ListBoxItem
menjadi tidak lebih dari ContentPresenter
, seperti ...
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Alasan saya untuk pendekatan ini adalah sebagai berikut:
Dalam kasus saya, saya tidak ingin menonaktifkan interaksi pengguna dengan konten saya ListBoxItems
sehingga solusi untuk mengatur IsEnabled
tidak akan berfungsi untuk saya.
Solusi lain yang mencoba untuk menata ulang gaya ListBoxItem
dengan menimpa properti terkait warna hanya berfungsi untuk kasus-kasus di mana Anda yakin template menggunakan properti tersebut. Itu bagus untuk gaya default, tetapi tidak cocok dengan gaya khusus.
Solusi yang menggunakan ItemsControl
istirahat terlalu banyak hal-hal lain sebagai ItemsControl
memiliki tampilan yang sama sekali berbeda dari standar ListBox
dan tidak mendukung virtualisasi, artinya Anda harus tetap kembali template ItemsPanel
.
Di atas tidak mengubah tampilan default ListBox
, tidak menonaktifkan item dalam templat data untuk ListBox
, mendukung virtualisasi secara default, dan bekerja secara independen dari gaya apa pun yang mungkin atau mungkin tidak digunakan dalam aplikasi Anda. Itu prinsip CIUMAN.
Catatan: Solusi ini tidak menonaktifkan pemilihan dengan navigasi keyboard atau mengklik kanan (mis. Tombol panah diikuti oleh tombol spasi)
Semua jawaban sebelumnya menghapus kemampuan pilih secara lengkap (tidak ada pergantian runtime) atau cukup hapus efek visual, tetapi bukan pilihan.
Tetapi bagaimana jika Anda ingin dapat memilih dan menunjukkan pilihan dengan kode, tetapi tidak dengan input pengguna? Mungkin Anda ingin "membekukan" pilihan pengguna tanpa menonaktifkan seluruh Listbox?
Solusinya adalah dengan membungkus seluruh ItemsContentTemplate menjadi Button yang tidak memiliki chrome visual. Ukuran tombol harus sama dengan ukuran Item, sehingga sepenuhnya tertutup. Sekarang gunakan tombol IsEnabled-Property:
Aktifkan tombol untuk "membekukan" status Pemilihan item. Ini berfungsi karena tombol yang diaktifkan memakan semua peristiwa mouse sebelum mereka menggelembung ke ListboxItem-Eventhandler. Emplate ItemDataTemplate Anda masih akan menerima MouseEvents karena itu bagian dari konten tombol.
Nonaktifkan tombol untuk mengaktifkan perubahan pilihan dengan mengklik.
<Style x:Key="LedCT" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Button IsEnabled="{Binding IsSelectable, Converter={StaticResource BoolOppositeConverter}}" Template="{DynamicResource InvisibleButton}">
<ContentPresenter />
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="InvisibleButton" TargetType="{x:Type Button}">
<ContentPresenter/>
</ControlTemplate>
dartrax
Mungkin Anda hanya membutuhkan fungsionalitas ItemsControl? Itu tidak memungkinkan seleksi:
<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />
Perbaikan sederhana yang berfungsi pada Windows Phone misalnya adalah pada pengaturan pilihan item yang dipilih ke nol:
<ListBox SelectionChanged="ListBox_SelectionChanged">
Dan dalam kode di belakang:
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
(sender as ListBox).SelectedItem = null;
}
Saya menemukan cara yang sempurna.
Set ListBox IsHitTestVisible menjadi false sehingga pengguna tidak dapat mengarahkan mouse atau gulir ke bawah atau gulir ke atas.
Capture PreviewGotKeyboardFocus e.Handled = true sehingga pengguna dapat memilih item dengan keyboard Tab, Panah atas, Panah bawah.
Keuntungan cara ini:
xmal
<ListBox Name="StudentsListBox" ItemsSource="{Binding Students}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" BorderThickness="0" Background="Transparent" IsHitTestVisible="False" PreviewGotKeyboardFocus="StudentsListBox_PreviewGotKeyboardFocus">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="Yellow" />
<Setter TargetName="Bd" Property="BorderBrush" Value="Transparent" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Name="GradeBlock" Text="{Binding Grade}" FontSize="12" Margin="0,0,5,0"/>
<TextBlock Grid.Column="1" Name="NameTextBlock" Text="{Binding Name}" FontSize="12" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
kode
private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
Bagi saya solusi terbaik adalah:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
IsEnabled = false
Untuk menonaktifkan satu atau lebih opsi di listbox / dropdown Anda, Anda dapat menambahkan atribut "dinonaktifkan" seperti yang ditunjukkan di bawah ini. Ini mencegah pengguna untuk memilih opsi ini, dan mendapat hamparan abu-abu.
ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);