WPF ListView tắt lựa chọn


119

Tôi có một WPF ListView đơn giản và một câu hỏi đơn giản:

Có thể tắt lựa chọn, vì vậy khi người dùng nhấp vào hàng, hàng không được đánh dấu?

ListView

Tôi muốn hàng 1 trông giống như hàng 0 khi được nhấp vào.

Có thể liên quan: tôi có thể tạo kiểu cho giao diện của di chuột / vùng chọn không? Ví dụ. để thay thế giao diện di chuột chuyển màu xanh lam (dòng 3) bằng một màu đồng nhất tùy chỉnh. Tôi đã tìm thấy cái nàycái này , tiếc là không giúp được gì.

(Đạt được điều tương tự mà không sử dụng ListView cũng có thể chấp nhận được. Tôi chỉ muốn có thể sử dụng cuộn logic và ảo hóa giao diện người dùng như ListView đã làm)

XAML cho ListView là:

<ListView Height="280" Name="listView">
    <ListView.Resources>
        <!-- attempt to override selection color -->
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightColorKey}"
                         Color="Green" />
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
                <!-- more columns -->
            </GridView.Columns>
        </GridView>
     </ListView.View>
</ListView>

Tôi chưa bao giờ sử dụng ListView trong WPF trước đây, nhưng tôi chắc chắn rằng có một số loại thuộc tính IsEnabled, nếu được đặt thành false, sẽ vô hiệu hóa toàn bộ kiểm soát và có thể sẽ đạt được những gì bạn đang theo đuổi, nhưng tôi không chắc chắn 100%.
James McConnell

Xin chào, có một thuộc tính IsEnabled, có thể vô hiệu hóa toàn bộ ListView. Tuy nhiên, tôi cần ListView hoạt động bình thường, chỉ không hiển thị lựa chọn.
Martin Konicek

Câu trả lời:


135

Theo nhận xét của Martin Konicek, để vô hiệu hóa hoàn toàn việc lựa chọn các mục theo cách đơn giản nhất:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </ListView.ItemContainerStyle>
    ...
</ListView>

Tuy nhiên, nếu bạn vẫn yêu cầu chức năng của ListView, chẳng hạn như có thể chọn một mục, thì bạn có thể tắt trực quan kiểu dáng của mục đã chọn như sau:

Bạn có thể thực hiện việc này theo một số cách, từ thay đổi ControlTemplate của ListViewItem đến chỉ thiết lập một kiểu (dễ dàng hơn nhiều). Bạn có thể tạo kiểu cho ListViewItems bằng ItemContainerStyle và 'tắt' cọ nền và đường viền khi nó được chọn.

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Style.Triggers>
                <Trigger Property="IsSelected"
                         Value="True">
                    <Setter Property="Background"
                            Value="{x:Null}" />
                    <Setter Property="BorderBrush"
                            Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListView.ItemContainerStyle>
    ...
</ListView>

Ngoài ra, trừ khi bạn có một số cách khác để thông báo cho người dùng khi mục được chọn (hoặc chỉ để thử nghiệm), bạn có thể thêm một cột để biểu thị giá trị:

<GridViewColumn Header="IsSelected"
                DisplayMemberBinding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />

2
Không thấy phần liên quan, nhưng bạn có thể làm điều tương tự, đặt nền và đường viền tùy thích trên thuộc tính IsMouseOver.
rmoore

88
Bây giờ tôi đã giải quyết nó tốt hơn - <Setter Property = "Focusable" Value = "false" /> hoàn toàn vô hiệu hóa việc chọn hàng.
Martin Konicek

8
Ahh, tôi nghĩ bạn chỉ cần tắt Lựa chọn một cách trực quan. Tuy nhiên, nếu bạn không muốn chúng được chọn, bạn có thể muốn xem xét bằng cách sử dụng ItemsControl (Vì bạn vẫn có thể đặt các mục đã chọn thông qua mã nếu chúng không thể tiêu điểm), tuy nhiên, để có được Grid trông bạn. Tôi sẽ phải làm điều gì đó như sau: manicprogrammer.com/cs/blogs/… Ngoài ra, nếu bạn chưa đọc, bạn có thể muốn xem cuốn sách WPF Unleashed, vì nó cung cấp một giới thiệu tuyệt vời về WPF & XAML.
rmoore

2
@MartinKonicek tôi biết đó là một bài cũ nhưng đánh giá bình luận cao của bạn nên được một câu trả lời;)
WiiMaxx

1
@MartinKonicek tôi đã có thêm BasedOn="{StaticResource {x:Type ListViewItem}}"nên nó không ghi đè lên phần còn lại của phong cách lưới của tôi, nhưng tôi cũng nghĩ bạn nên bình luận của bạn câu trả lời được chấp nhận
JumpingJezza

31

Câu trả lời của Moore không hoạt động và trang ở đây:

Chỉ định Màu lựa chọn, Căn chỉnh nội dung và Màu nền cho các mục trong ListBox

giải thích tại sao nó không thể hoạt động.

Nếu chế độ xem danh sách của bạn chỉ chứa văn bản cơ bản, cách đơn giản nhất để giải quyết vấn đề là sử dụng bút vẽ trong suốt.

<Window.Resources>
  <Style TargetType="{x:Type ListViewItem}">
    <Style.Resources>
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#00000000"/>
      <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#00000000"/>
    </Style.Resources>
  </Style>
</Window.Resources>

Điều này sẽ tạo ra kết quả không mong muốn nếu các ô của listview đang giữ các điều khiển như hộp tổ hợp, vì nó cũng thay đổi màu của chúng. Để giải quyết vấn đề này, bạn phải xác định lại mẫu của điều khiển.

  <Window.Resources>
    <Style TargetType="{x:Type ListViewItem}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type ListViewItem}">
            <Border SnapsToDevicePixels="True" 
                    x:Name="Bd" 
                    Background="{TemplateBinding Background}" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    Padding="{TemplateBinding Padding}">
              <GridViewRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                    Columns="{TemplateBinding GridView.ColumnCollection}" 
                                    Content="{TemplateBinding Content}"/>
            </Border>
            <ControlTemplate.Triggers>
              <Trigger Property="IsEnabled" 
                       Value="False">
                <Setter Property="Foreground" 
                        Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Window.Resources>

14
Điều này làm cho tất cả các mục của tôi trong ListView của tôi biến mất
Chuck Savage

18

Đặt kiểu của mỗi ListViewItem để Focusable được đặt thành false.

<ListView ItemsSource="{Binding Test}" >
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

4
Đơn giản và hiệu quả. Và nó thực sự làm những gì được yêu cầu: Nó tắt lựa chọn thay vì chỉ ẩn nó. Đây là câu trả lời tốt nhất.
Fumidu

13

Đây là mẫu mặc định cho ListViewItem từ Blend:

Mẫu ListViewItem mặc định:

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true"/>
                                <Condition Property="Selector.IsSelectionActive" Value="false"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

Chỉ cần loại bỏ IsSelected Trigger và IsSelected / IsSelectionActive MultiTrigger, bằng cách thêm mã bên dưới vào Style của bạn để thay thế mẫu mặc định và sẽ không có thay đổi trực quan nào khi được chọn.

Giải pháp để tắt các thay đổi trực quan của thuộc tính IsSelected:

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

12

Cách dễ nhất mà tôi tìm thấy:

<Setter Property="Focusable" Value="false"/>

4
@Mutex Nó hoạt động - bạn phải áp dụng điều này ListView.ItemContainerStyle!
Andreas Niedermair

8

Ngoài giải pháp ở trên ... Tôi sẽ sử dụng MultiTrigger để cho phép các điểm nổi bật của MouseOver tiếp tục hoạt động sau khi chọn sao cho kiểu ListViewItem của bạn sẽ là:

        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Style.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="True" />
                            <Condition Property="IsMouseOver" Value="False" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background" Value="{x:Null}" />
                            <Setter Property="BorderBrush" Value="{x:Null}" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>

6

Được rồi, trò chơi hơi muộn, nhưng không có giải pháp nào trong số này thực hiện được những gì tôi đang cố gắng làm. Các giải pháp này có một số vấn đề

  1. Vô hiệu hóa ListViewItem, điều này làm tăng kiểu dáng và vô hiệu hóa tất cả các điều khiển con
  2. Xóa khỏi ngăn xếp thử nghiệm lần truy cập, tức là các điều khiển trẻ em không bao giờ được di chuột qua hoặc nhấp
  3. Làm cho nó không tập trung được, điều này đơn giản không hiệu quả với tôi?

Tôi muốn có một ListView với các tiêu đề nhóm và mỗi ListViewItem chỉ nên 'thông tin' mà không cần chọn hoặc di chuột qua, nhưng ListViewItem có một nút trong đó mà tôi muốn có thể nhấp và di chuột qua.

Vì vậy, thực sự những gì tôi muốn là ListViewItem hoàn toàn không phải là một ListViewItem, Vì vậy, tôi đã vượt qua ControlTemplate của ListViewItem và chỉ biến nó thành ContentControl đơn giản.

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <ContentControl Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"/>
                </ControlTemplate>
            </Setter.Value>
         </Setter>
     </Style>
</ListView.ItemContainerStyle>

5

Một trong những thuộc tính của listview là IsHitTestVisible. Bỏ chọn nó.


Đơn giản và hiệu quả, cũng giải quyết vấn đề của tôi với ScrollViewer được bao bọc bên ngoài chế độ xem danh sách.
Brian Ng

1
Tôi có mẫu nút bên trong danh sách itemtemplate. nếu bỏ chọn IsHitTestVisiblethì không thể nhấp vào nút. Nó hoạt động giống nhưIsEnabled = false;
Luiey

1

Điều này dành cho những người khác có thể gặp phải các yêu cầu sau:

  1. Thay thế hoàn toàn chỉ báo trực quan của "đã chọn" (ví dụ: sử dụng một số loại hình dạng), ngoài việc chỉ thay đổi màu của điểm đánh dấu tiêu chuẩn
  2. Bao gồm chỉ báo đã chọn này trong DataTemplate cùng với các trình bày trực quan khác về mô hình của bạn, nhưng,
  3. Không muốn phải thêm thuộc tính "IsSelectedItem" vào lớp mô hình của bạn và phải chịu gánh nặng với việc thao tác thủ công thuộc tính đó trên tất cả các đối tượng mô hình.
  4. Yêu cầu các mục có thể chọn được trong ListView
  5. Cũng muốn thay thế hình ảnh đại diện của IsMouseOver

Nếu bạn giống tôi (sử dụng WPF với .NET 4.5) và nhận thấy rằng các giải pháp liên quan đến trình kích hoạt kiểu đơn giản không hoạt động, đây là giải pháp của tôi:

Thay thế ControlTemplate của ListViewItem theo kiểu:

<ListView ItemsSource="{Binding MyStrings}" ItemTemplate="{StaticResource dtStrings}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListViewItem">
                            <ContentPresenter/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

..Và DataTemplate:

<DataTemplate x:Key="dtStrings">
        <Border Background="LightCoral" Width="80" Height="24" Margin="1">
            <Grid >
                <Border Grid.ColumnSpan="2" Background="#88FF0000" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsMouseOver, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}"/>
                <Rectangle Grid.Column="0" Fill="Lime" Width="10" HorizontalAlignment="Left" Visibility="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected, Converter={StaticResource conBoolToVisibilityTrueIsVisibleFalseIsCollapsed}}" />
                <TextBlock Grid.Column="1" Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
            </Grid>
        </Border>
    </DataTemplate>

Kết quả này trong thời gian chạy (mục 'B' được chọn, mục 'D' được di chuột qua):

Giao diện ListView


1

Sử dụng mã bên dưới:

   <ListView.ItemContainerStyle>
          <Style TargetType="{x:Type ListViewItem}">
           <Setter Property="Background" Value="Transparent`enter code here`" />
             <Setter Property="Template">
               <Setter.Value>
                 <ControlTemplate TargetType="{x:Type ListViewItem}">
                   <ContentPresenter />
                 </ControlTemplate>
               </Setter.Value>
             </Setter>
          </Style>
   </ListView.ItemContainerStyle>

0

Mã bên dưới vô hiệu hóa lựa chọn hàng ListViewItem và cũng cho phép thêm phần đệm, lề, v.v.

<ListView.ItemContainerStyle>                                                                              
   <Style TargetType="ListViewItem">                                                                                      
       <Setter Property="Template">                                                                                            
         <Setter.Value>                                                                                             
           <ControlTemplate TargetType="{x:Type ListViewItem}">                                                                                                    
              <ListViewItem Padding="0" Margin="0">                                                                                                        
                  <ContentPresenter />
              </ListViewItem>
           </ControlTemplate>                                                          
         </Setter.Value>                                                                                       
         </Setter>
      </Style>                                                                      
  </ListView.ItemContainerStyle> 

0

Mã bên dưới vô hiệu hóa Focus on ListViewItem

<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

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.