Không có ListBox.SelectionMode = không có ai, có cách nào khác để vô hiệu hóa lựa chọn trong hộp danh sách không?


188

Làm cách nào để tắt lựa chọn trong ListBox?


1
Bạn có thể cung cấp một ví dụ hợp lệ để có ListBox mà bạn không thể chọn không? Vì hành vi chính là chọn vật phẩm. Tôi có lẽ đã chọn một cách khác để hiển thị nó (Đây không phải là tôi đang cố gắng trở thành một nhà phê bình mà là một mối quan tâm thực sự về nơi điều này có thể xảy ra)
Marthin

3
@Martin: ví dụ: nếu bạn muốn kéo nội dung từ listboxitem - trong trường hợp này có lẽ bạn không quan tâm đến việc chọn mục đó. CSONG: khi kéo một mục: mục được chọn của hộp danh sách sẽ thay đổi trong khi bạn kéo trong hộp danh sách - xem bài đăng này stackoverflow.com/questions/7589142/
Lỗi

1
Tôi tin rằng lý do mà Shimmy muốn sử dụng ListBox là vì người hỏi có thể làm cho hộp danh sách có thể được chọn đôi khi. Câu hỏi cũng có giá trị với tôi. Giả sử bạn đang xây dựng một trò chơi bài. Bạn có thể chọn một thẻ từ thẻ của mình, đôi khi, bạn có thể chọn nhiều thẻ và vào những thời điểm khác, bạn không thể chọn bất kỳ thẻ nào.
Gqqnbig

1
Thêm vào đó, đôi khi bạn có 10 thẻ và chỉ 4 trong số đó là có thể lựa chọn. Trong số 4, bạn có thể chọn tối đa 3.
Gqqnbig

1
@Marthin: Khi bạn có GridView trong ListBox. Tiêu đề Gridview cung cấp rất nhiều chức năng không có sẵn ở nơi khác. Và bạn có các điều khiển chỉnh sửa trong các ô của Gridview.
Robin Davies

Câu trả lời:


264

Cách tiếp cận 1 - ItemsControl

Trừ khi bạn cần các khía cạnh khác của ListBox, ItemsControlthay vào đó , bạn có thể sử dụng . Nó đặt các mục trong ItemsPanelvà không có khái niệm lựa chọn.

<ItemsControl ItemsSource="{Binding MyItems}" />

Theo mặc định, ItemsControlkhông hỗ trợ ảo hóa các phần tử con của nó. Nếu bạn có nhiều mục, ảo hóa có thể giảm mức sử dụng bộ nhớ và cải thiện hiệu suất, trong trường hợp đó bạn có thể sử dụng phương pháp 2 và tạo kiểu ListBoxhoặc thêm ảo hóa vàoItemsControl .

Cách tiếp cận 2 - Tạo kiểu ListBox

Ngoài ra, chỉ cần tạo kiểu cho ListBox sao cho lựa chọn không hiển thị.

<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>

24
không, nó sẽ chỉ thay đổi hiệu ứng hình ảnh, không phải hành vi lựa chọn thực tế
Thomas Levesque

8
Đề nghị đầu tiên của tôi là sử dụng ItemControl. Bạn đã bỏ lỡ điều đó? :)
vẽ Noakes

5
Đọc lại những bình luận này một lần nữa tôi muốn chỉ ra rằng nhận xét của @Thomas Levesque chỉ đúng với cách tiếp cận thứ hai tôi trình bày. Sử dụng đồng bằng ItemsControlsẽ loại bỏ hoàn toàn bất kỳ khái niệm lựa chọn.
Drew Noakes

1
Giải pháp ItemControl loại bỏ hỗ trợ cuộn hộp (thanh cuộn và con lăn chuột).
MũiBienCarlota

1
+1 cho Cách tiếp cận 1 - ItemControl. Nếu chúng ta có một trang lớn mà chúng ta phải cuộn, nếu người dùng lướt qua ListBox, nó sẽ vô hiệu hóa MouseWheel một cách hiệu quả khi hộp danh sách lấy các sự kiện của MouseWheel. Điều này có nghĩa là người dùng cảm thấy thất vọng vì con chuột được sử dụng để cuộn toàn bộ trang sẽ ngẫu nhiên ngừng hoạt động, tùy thuộc vào việc con chuột có nằm trong hộp danh sách hay không.
Contango

159

Tôi tìm thấy một giải pháp rất đơn giản và thẳng tiến làm việc cho tôi, tôi hy vọng nó cũng sẽ làm cho bạn

<ListBox ItemsSource="{Items}">
    <ListBox.ItemContainerStyle>
       <Style TargetType="{x:Type ListBoxItem}">
           <Setter Property="Focusable" Value="False"/>
       </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Tôi nghĩ rằng anh ấy đã trải qua điều đó khá tốt ở đây: asaddurrani.wordpress.com/tag/wpf-listbox-disable-selection
Sid

3
Đây là hoàn hảo. nó ngăn mục được chọn và các điều khiển khác như các nút vẫn hoạt động. chính xác những gì tôi đang tìm kiếm
Franck

1
+1 cho phương pháp này. Nếu chúng ta có một trang lớn mà chúng ta phải cuộn, nếu người dùng lướt qua ListBox, nó sẽ vô hiệu hóa MouseWheel một cách hiệu quả khi hộp danh sách lấy các sự kiện của MouseWheel. Điều này có nghĩa là người dùng cảm thấy thất vọng vì con chuột được sử dụng để cuộn toàn bộ trang sẽ ngẫu nhiên ngừng hoạt động, tùy thuộc vào việc con chuột có nằm trong hộp danh sách hay không.
Contango

Thông minh. Cách tiếp cận tương tự cũng có hiệu quả đối với tôi khi tôi cần các nút trên các mục không gây ra lựa chọn vật phẩm - nhưng chỉ khi khu vực khác của vật phẩm được nhấp. Đơn giản chỉ cần đặt các nút Focusable = "False"!
Jony Adamit

1
Thêm thuộc tính bổ sung này để xóa phần tô sáng di chuột cũng: <Setter Property="IsHitTestVisible" Value="False" />
DonBoitnott

25

Bạn có thể chuyển sang sử dụng ItemsControlthay vì a ListBox. An ItemsControlkhông có khái niệm về lựa chọn, vì vậy không có gì để tắt.


2
Duyên dáng. Tôi không bao giờ biết bạn có thể trực tiếp khai báo ItemControl, tôi nghĩ đó là ảo (MustOverride), cảm ơn !!!
Shimmy Weitzhandler

Nhưng ItemControl vẫn kết xuất các mục của tôi trong một dòng chứ?
Chry Cheng

@ Hãy thử có, và ngoài ra, bạn luôn có thể đặt thủ công ItemTemplate.
Shimmy Weitzhandler

2
Điều này kết thúc việc mất quá nhiều chức năng - ví dụ, cuộn.
Jeff

@Jeff bạn có thể bọc ItemControl trong ScrollViewer để cuộn.
Wilka

12

Một tùy chọn khác đáng xem xét là vô hiệu hóa ListBoxItems. Điều này có thể được thực hiện bằng cách đặt ItemContainerStyle như trong đoạn trích sau.

<ListBox ItemsSource="{Binding YourCollection}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsEnabled" Value="False" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Nếu bạn không muốn văn bản có màu xám, bạn có thể chỉ định màu bị tắt bằng cách thêm một cọ vào tài nguyên của kiểu bằng khóa sau: {x: Tĩnh SystemColors.GrayTextBrushKey}. Giải pháp khác là ghi đè lên mẫu điều khiển ListBoxItem.


Đơn giản và làm việc, cảm ơn! Và nó cũng có thể áp dụng trên WP 8.1 Runtime.
Malutek

8

Điều này cũng sẽ hoạt động, nếu tôi có nhu cầu sử dụng listbox thay vì các mục điều khiển, nhưng tôi chỉ hiển thị các mục không thể chọn, tôi sử dụng:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="IsHitTestVisible" Value="False" />
    </Style>
</ListBox.ItemContainerStyle>

3

Khá nhiều câu trả lời hay ở đây, nhưng tôi đang tìm kiếm một điều hơi khác: tôi muốn lựa chọn, nhưng chỉ không muốn nó được hiển thị (hoặc hiển thị trong một vấn đề khác).

Các giải pháp ở trên không hiệu quả với tôi (hoàn toàn), vì vậy tôi đã làm một việc khác: Tôi đã sử dụng một kiểu mới cho hộp danh sách của mình, định nghĩa lại hoàn toàn các mẫu:

<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>

Bắt đầu với điều đó, bạn có thể dễ dàng thêm phần tô sáng lựa chọn của riêng bạn hoặc để nó như thế nếu bạn không muốn chút nào.


2

Mặc dù câu trả lời của @Drew Noakes là một giải pháp nhanh chóng cho hầu hết các trường hợp, có một chút sai sót khi cài đặt các bàn chải x: Tĩnh.

Khi bạn đặt các bàn chải x: Tĩnh như được đề xuất, tất cả các điều khiển con trong mục hộp danh sách sẽ kế thừa kiểu này.

Điều đó có nghĩa là, trong khi điều này sẽ hoạt động để vô hiệu hóa phần tô sáng của mục hộp danh sách, nó có thể dẫn đến các hiệu ứng không mong muốn cho các điều khiển con.

Ví dụ: nếu bạn có ComboBox trong ListBoxItem, nó sẽ vô hiệu hóa chuột trên phần tô sáng trong ComboBox.

Thay vào đó, hãy xem xét việc thiết lập VisualStates cho các sự kiện đã chọn, không được chọn và MouseOver như được đề cập trong giải pháp được đề cập trong luồng stackoverflow này: Xóa Control Highlight khỏi ListBoxItem nhưng không điều khiển con .

-Frinny


2

Tôi đề xuất một giải pháp khác. Đơn giản chỉ cần đặt lại mẫu ListBoxItemđể không có gì hơn một ContentPresenter, như vậy ...

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Lý do của tôi cho cách tiếp cận này là như sau:

  1. Trong trường hợp của tôi, tôi không muốn vô hiệu hóa tương tác của người dùng với nội dung của mình ListBoxItemsđể giải pháp thiết lập IsEnabledsẽ không hiệu quả với tôi.

  2. Giải pháp khác cố gắng định kiểu lại ListBoxItembằng cách ghi đè các thuộc tính liên quan đến màu sắc chỉ hoạt động cho những trường hợp mà bạn chắc chắn mẫu sử dụng các thuộc tính đó. Điều đó tốt cho các kiểu mặc định, nhưng phá vỡ các kiểu tùy chỉnh.

  3. Các giải pháp sử dụng ItemsControlphá vỡ quá nhiều thứ khác vì nó ItemsControlcó giao diện hoàn toàn khác so với tiêu chuẩn ListBoxvà không hỗ trợ ảo hóa, nghĩa là bạn phải tạo lại mẫu bằng ItemsPanelmọi cách.

Ở trên không thay đổi giao diện mặc định của ListBox, không vô hiệu hóa các mục trong các mẫu dữ liệu cho ListBox, hỗ trợ ảo hóa theo mặc định và hoạt động độc lập với bất kỳ kiểu nào có thể hoặc không được sử dụng trong ứng dụng của bạn. Đó là nguyên tắc KISS.


1

Lưu ý: Giải pháp này không vô hiệu hóa lựa chọn bằng điều hướng bàn phím hoặc nhấp chuột phải (ví dụ: phím mũi tên theo sau là phím cách)

Tất cả các câu trả lời trước đó đều loại bỏ khả năng chọn hoàn toàn (không chuyển đổi trong thời gian chạy) hoặc đơn giản là loại bỏ hiệu ứng hình ảnh, nhưng không loại bỏ lựa chọn.

Nhưng nếu bạn muốn có thể chọn và hiển thị lựa chọn theo mã, nhưng không phải bằng đầu vào của người dùng thì sao? Có thể bạn muốn "đóng băng" lựa chọn của người dùng trong khi không vô hiệu hóa toàn bộ Listbox?

Giải pháp là bọc toàn bộ ItemContentTemplate vào một Nút không có chrome trực quan. Kích thước của nút phải bằng kích thước của Vật phẩm, vì vậy nó được bao phủ hoàn toàn. Bây giờ sử dụng IsEnables-property của nút:

Kích hoạt nút "đóng băng" trạng thái Lựa chọn của vật phẩm. Điều này hoạt động vì nút được kích hoạt ăn tất cả các sự kiện chuột trước khi chúng nổi lên với ListboxItem-Eventhandler. ItemDataTemplate của bạn vẫn sẽ nhận được MouseEvents vì đây là một phần của nội dung các nút.

Vô hiệu hóa nút để cho phép thay đổi lựa chọn bằng cách nhấp vào.

<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>

phi tiêu


1

Có lẽ bạn cần chức năng onlly của ItemControl? Nó không cho phép lựa chọn:

<ItemsControl ItemsSource="{Binding Prop1}" ItemTemplate="{StaticResource DataItemsTemplate}" />

3
@Shimmy: Thông thường các câu trả lời tầm thường là tương tự nhau. Không có sự trùng lặp ở đây xứng đáng với bất kỳ cờ nào. Nếu bạn có thêm câu hỏi nào về vấn đề này, vui lòng hỏi về Meta Stack Overflow .

0

Bạn có thể đặt Textblock phía trên hộp danh sách của mình, nó sẽ không thay đổi giao diện của ứng dụng của bạn và cũng không cho phép chọn bất kỳ mục nào.


1
Bạn vẫn sẽ cần phải vô hiệu hóa điều hướng tab, mặc dù.
Amanduh

0

Một sửa chữa đơn giản hoạt động trên Windows Phone chẳng hạn là trên cài đặt lựa chọn mục đã chọn thành null:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

Và trong mã phía sau:

    private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        (sender as ListBox).SelectedItem = null;
    }

0

Tôi tìm thấy một cách hoàn hảo.
Đặt ListBox IsHitTestVisible thành false để người dùng không thể di chuột hoặc cuộn xuống hoặc cuộn lên.
Chụp bản xem trướcGotPalF Focus e.Handled = true để người dùng có thể chọn mục bằng Tab bàn phím, Mũi tên lên, Mũi tên xuống.

Cách này lợi thế:

  1. Các mục ListBox Tiền cảnh sẽ không trở thành Màu xám.
  2. Nền ListBox có thể được đặt thành Trong suốt

xody

<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>

private void StudentsListBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    e.Handled = true;
}

-1

Đối với tôi giải pháp tốt nhất là:

        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Focusable" Value="True"/>
                <Setter Property="IsHitTestVisible" Value="False" />
            </Style>
        </ListBox.ItemContainerStyle>

-3

IsEnables = false


2
Nó làm cho nó toàn màu xám, đây không phải là thứ tôi đang tìm kiếm
Shimmy Weitzhandler

1
Nhưng đó là một câu trả lời đơn giản cho câu hỏi đơn giản :)
Viktor Jevdokimov

1
Câu trả lời thẳng thắn là stackoverflow.com/questions/1398559/1398650#1398650 , nhưng dù sao cũng cảm ơn
Shimmy Weitzhandler

Rất giúp đỡ cho tôi, tôi muốn màu xám và tàn tật!
Martin Robins

-3

Để vô hiệu hóa một hoặc nhiều tùy chọn trong hộp danh sách / thả xuống của bạn, bạn có thể thêm thuộc tính "bị vô hiệu hóa" như hiển thị bên dưới. Điều này ngăn người dùng chọn tùy chọn này và nó có lớp phủ màu xám.

ListItem item = new ListItem(yourvalue, yourkey);
item.Attributes.Add("disabled","disabled");
lb1.Items.Add(item);

Lúc đó bạn đã cao và trả lời một câu hỏi WPF bằng một giải pháp ASP.NET.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.