WPF ListView ปิดการเลือก


122

ฉันมี WPF ListView ง่ายๆและคำถามง่ายๆ:

เป็นไปได้ไหมที่จะปิดการเลือกดังนั้นเมื่อผู้ใช้คลิกแถวแถวนั้นจะไม่ถูกไฮไลต์

ListView

ฉันต้องการให้แถวที่ 1 ดูเหมือนกับแถว 0 เมื่อคลิก

อาจเกี่ยวข้อง: ฉันสามารถกำหนดรูปลักษณ์ของโฮเวอร์ / การเลือกได้หรือไม่? เช่น. เพื่อแทนที่รูปลักษณ์ของโฮเวอร์ไล่ระดับสีน้ำเงิน (บรรทัด 3) ด้วยสีทึบที่กำหนดเอง ฉันได้พบสิ่งนี้และสิ่งนี้น่าเสียดายที่ไม่ได้ช่วย

(การบรรลุสิ่งเดียวกันโดยไม่ใช้ ListView ก็ยอมรับได้เช่นกันฉันแค่อยากจะสามารถใช้การเลื่อนแบบลอจิคัลและการจำลองเสมือน UI เหมือนที่ ListView ทำ)

XAML สำหรับ ListView คือ:

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

ฉันไม่เคยใช้ ListView ใน WPF มาก่อน แต่ฉันแน่ใจว่ามีคุณสมบัติ IsEnabled บางประเภทที่หากตั้งค่าเป็นเท็จจะปิดใช้งานการควบคุมทั้งหมดและอาจจะบรรลุสิ่งที่คุณต้องการ แต่ฉัน ไม่แน่ใจ 100%
James McConnell

สวัสดีใช่มีคุณสมบัติ IsEnabled ซึ่งสามารถปิดใช้งาน ListView ทั้งหมดได้ ฉันต้องการให้ ListView ทำงานได้ตามปกติ แต่อย่าแสดงสิ่งที่เลือก
Martin Konicek

คำตอบ:


137

ตามความคิดเห็นของ Martin Konicek เพื่อปิดการใช้งานการเลือกรายการในลักษณะที่ง่ายที่สุด:

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

อย่างไรก็ตามหากคุณยังต้องการฟังก์ชั่นของ ListView เช่นความสามารถในการเลือกรายการคุณสามารถปิดการใช้งานรูปแบบของรายการที่เลือกด้วยสายตาได้ดังนี้:

คุณสามารถทำได้หลายวิธีตั้งแต่การเปลี่ยนControlTemplateของ ListViewItem ไปจนถึงการตั้งค่าสไตล์ (ง่ายกว่ามาก) คุณสามารถสร้างสไตล์สำหรับ ListViewItems โดยใช้ItemContainerStyleและ 'ปิด' พื้นหลังและแปรงเส้นขอบเมื่อถูกเลือก

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

นอกจากนี้เว้นแต่คุณจะมีวิธีอื่นในการแจ้งผู้ใช้เมื่อมีการเลือกรายการ (หรือเพื่อการทดสอบ) คุณสามารถเพิ่มคอลัมน์เพื่อแสดงค่าได้:

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

2
ไม่เห็นส่วนที่เกี่ยวข้อง แต่คุณสามารถทำสิ่งเดียวกันได้โดยตั้งค่าพื้นหลังและเส้นขอบตามที่คุณต้องการบนคุณสมบัติ IsMouseOver
rmoore

88
ตอนนี้ฉันแก้ไขได้ดียิ่งขึ้น - <Setter Property = "Focusable" Value = "false" /> ปิดใช้งานการเลือกแถวโดยสิ้นเชิง
Martin Konicek

8
อ่าฉันคิดว่าคุณหมายถึงแค่ปิดการเลือกด้วยสายตา หากคุณไม่ต้องการให้เลือกเลยคุณอาจต้องการดูที่การใช้ ItemsControl (เนื่องจากคุณยังสามารถตั้งค่ารายการที่เลือกผ่านรหัสได้หากไม่สามารถโฟกัสได้) แม้ว่าจะทำให้กริดดูคุณ จะต้องทำสิ่งนี้: manicprogrammer.com/cs/blogs/…นอกจากนี้หากคุณยังไม่ได้อ่านคุณอาจต้องการดูหนังสือ WPF Unleashed เนื่องจากมีการแนะนำ WPF & XAML ที่ยอดเยี่ยม
rmoore

2
@MartinKonicek ฉันรู้ว่านั่นเป็นโพสต์เก่า แต่ความคิดเห็นที่ได้รับคะแนนสูงของคุณควรเป็นคำตอบ)
WiiMaxx

1
@MartinKonicek ฉันต้องเพิ่มBasedOn="{StaticResource {x:Type ListViewItem}}"ดังนั้นมันจึงไม่ได้แทนที่รูปแบบกริดที่เหลือของฉัน แต่ฉันคิดว่าคุณควรแสดงความคิดเห็นของคุณเป็นคำตอบที่ยอมรับ
JumpingJezza

31

คำตอบของมัวร์ใช้ไม่ได้และหน้านี้:

การระบุสีที่เลือกการจัดแนวเนื้อหาและสีพื้นหลังสำหรับรายการในกล่องรายการ

อธิบายว่าเหตุใดจึงไม่สามารถทำงานได้

หากมุมมองรายการของคุณมีเฉพาะข้อความพื้นฐานวิธีที่ง่ายที่สุดในการแก้ปัญหาคือการใช้แปรงโปร่งใส

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

สิ่งนี้จะให้ผลลัพธ์ที่ไม่พึงปรารถนาหากเซลล์ของ listview มีการควบคุมเช่น comboboxes เนื่องจากมันเปลี่ยนสีด้วย ในการแก้ปัญหานี้คุณต้องกำหนดเทมเพลตของตัวควบคุมใหม่

  <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
สิ่งนี้ทำให้รายการทั้งหมดของฉันใน ListView ของฉันหายไป
Chuck Savage

18

ตั้งค่าสไตล์ของ ListViewItem แต่ละรายการให้ตั้งค่า Focusable เป็นเท็จ

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

4
ง่ายและมีประสิทธิภาพ และมันก็ทำตามที่ถามจริงๆ: ปิดการเลือกแทนที่จะซ่อนไว้ นี่คือคำตอบที่ดีที่สุด
Fumidu

13

นี่คือเทมเพลตเริ่มต้นสำหรับ ListViewItem จาก Blend:

เทมเพลต ListViewItem เริ่มต้น:

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

เพียงแค่ลบ IsSelected Trigger และ IsSelected / IsSelectionActive MultiTrigger โดยการเพิ่มโค้ดด้านล่างในสไตล์ของคุณเพื่อแทนที่เทมเพลตเริ่มต้นและจะไม่มีการเปลี่ยนแปลงภาพเมื่อเลือก

วิธีการปิดการเปลี่ยนแปลงภาพของคุณสมบัติ 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>


8

นอกเหนือจากวิธีแก้ปัญหาข้างต้น ... ฉันจะใช้ MultiTrigger เพื่อให้ไฮไลต์ของ MouseOver ทำงานต่อไปหลังจากที่เลือกเพื่อให้สไตล์ ListViewItem ของคุณเป็น:

        <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

โอเคช้าไปหน่อยสำหรับเกม แต่ไม่มีวิธีแก้ปัญหาเหล่านี้ที่ทำได้ในสิ่งที่ฉันพยายามทำ โซลูชันเหล่านี้มีปัญหาสองสามประการ

  1. ปิดการใช้งาน ListViewItem ซึ่งจะทำให้สไตล์และปิดการใช้งานการควบคุมเด็กทั้งหมด
  2. ลบออกจากสแต็กการทดสอบการโจมตีกล่าวคือเด็ก ๆ ควบคุมไม่เคยวางเมาส์หรือคลิก
  3. ทำให้มันโฟกัสไม่ได้ธรรมดาแค่นี้ใช้ไม่ได้เหรอ

ฉันต้องการ ListView ที่มีส่วนหัวการจัดกลุ่มและ ListViewItem แต่ละรายการควรเป็น 'ข้อมูล' โดยไม่ต้องเลือกหรือวางเมาส์เหนือ แต่ ListViewItem มีปุ่มที่ฉันต้องการให้สามารถคลิกได้และวางเมาส์ไว้เหนือ

ดังนั้นสิ่งที่ฉันต้องการจริงๆคือ ListViewItem ไม่ใช่ ListViewItem เลยดังนั้นฉันจึงขี่ ControlTemplate ของ ListViewItem และทำให้มันเป็น ContentControl อย่างง่าย

<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

หนึ่งในคุณสมบัติของ ListView IsHitTestVisibleเป็น ยกเลิกการเลือก


ง่ายและมีประสิทธิภาพแก้ปัญหาของฉันด้วย ScrollViewer ที่ห่อมุมมองรายการออกด้านข้าง
Brian Ng

1
ฉันได้รับเทมเพลตปุ่มในรายการมุมมองรายการ หากยกเลิกการเลือกIsHitTestVisibleปุ่มจะไม่สามารถคลิกได้ มันทำเหมือนIsEnabled = false;
Luiey

1

สำหรับผู้อื่นที่อาจพบข้อกำหนดดังต่อไปนี้:

  1. แทนที่การแสดงภาพของ "เลือก" โดยสิ้นเชิง (เช่นใช้รูปร่างบางประเภท) นอกเหนือจากการเปลี่ยนสีของไฮไลต์มาตรฐาน
  2. รวมการบ่งชี้ที่เลือกนี้ใน DataTemplate พร้อมกับการแสดงภาพอื่น ๆ ของโมเดลของคุณ แต่
  3. ไม่ต้องการเพิ่มคุณสมบัติ "IsSelectedItem" ลงในคลาสโมเดลของคุณและต้องรับภาระกับการจัดการคุณสมบัตินั้นด้วยตนเองในวัตถุโมเดลทั้งหมด
  4. กำหนดให้รายการสามารถเลือกได้ใน ListView
  5. ยังต้องการแทนที่การแสดงภาพของ IsMouseOver

หากคุณเป็นเหมือนฉัน (ใช้ WPF กับ. NET 4.5) และพบว่าโซลูชันที่เกี่ยวข้องกับทริกเกอร์สไตล์ไม่ได้ผลนี่คือวิธีแก้ปัญหาของฉัน:

แทนที่ ControlTemplate ของ ListViewItem ในรูปแบบ:

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

.. และ 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>

ผลลัพธ์ในขณะรันไทม์ (เลือกรายการ 'B', รายการ 'D' วางเมาส์เหนือ):

ลักษณะ ListView


1

ใช้รหัสร้อง:

   <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

ด้านล่างรหัสปิดใช้งานการเลือกแถว ListViewItem และยังอนุญาตให้เพิ่มช่องว่างระยะขอบ ฯลฯ

<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

ด้านล่างรหัสปิดใช้งาน 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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.