ไม่มี ListBox.SelectionMode =“ ไม่มี” มีวิธีปิดการเลือกในกล่องรายการอีกหรือไม่


189

ฉันจะปิดการใช้งานการเลือกในกล่องรายการได้อย่างไร


1
คุณสามารถให้ตัวอย่างที่ถูกต้องมีกล่องรายการที่คุณไม่สามารถเลือกได้หรือไม่ เนื่องจากพฤติกรรมหลักคือการเลือกรายการ ฉันอาจจะเลือกวิธีอื่นในการแสดง (นี่ไม่ใช่ฉันพยายามเป็นนักวิจารณ์ แต่เป็นความสนใจที่แท้จริงที่อาจเกิดขึ้นได้)
Marthin

3
@Martin: ตัวอย่างเช่นหากคุณต้องการลากเนื้อหาจาก listboxitem - ในกรณีนี้คุณอาจไม่สนใจเลือกรายการนั้น นอกจากนี้: เมื่อลากรายการ: รายการที่เลือกของการเปลี่ยนแปลงรายการในขณะที่คุณลากภายในกล่องรายการ - ดูโพสต์นี้stackoverflow.com/questions/7589142/…
Danield

1
ฉันเชื่อว่าเหตุผลที่ Shimmy ต้องการใช้กล่องรายการคือผู้ถามสามารถเลือกกล่องรายการได้ในบางครั้ง คำถามก็มีค่าสำหรับฉันเช่นกัน สมมติว่าคุณกำลังสร้างเกมไพ่ คุณสามารถเลือกหนึ่งบัตรจากบัตรของคุณบางครั้งคุณสามารถเลือกหลาย ๆ บัตรและในเวลาอื่น ๆ คุณไม่สามารถเลือกใด ๆ
Gqqnbig

1
นอกจากนี้บางครั้งคุณมีไพ่ 10 ใบและเลือกได้เพียง 4 ใบเท่านั้น ในบรรดา 4 คุณสามารถเลือกได้ถึง 3
Gqqnbig

1
@Marthin: เมื่อคุณมี GridView ในกล่องรายการ ส่วนหัวของ Gridview มีฟังก์ชั่นมากมายที่ไม่สามารถหาได้จากที่อื่น และคุณมีตัวควบคุมการแก้ไขในเซลล์ของ gridview
Robin Davies

คำตอบ:


264

วิธีที่ 1 - ItemsControl

ถ้าคุณไม่ต้องการแง่มุมอื่น ๆ ของListBoxคุณสามารถใช้ItemsControlแทน มันวางรายการในItemsPanelและไม่มีแนวคิดในการเลือก

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

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

วิธีที่ 2 - การใส่สไตล์ ListBox

หรือเพียงแค่กำหนดสไตล์กล่องรายการเพื่อไม่ให้มองเห็นสิ่งที่เลือก

<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
ไม่มันจะเปลี่ยนเอฟเฟ็กต์ภาพเท่านั้นไม่ใช่พฤติกรรมการเลือกจริง
Thomas Levesque

8
คำแนะนำแรกของฉันคือการใช้ ItemsControl คุณคิดถึงสิ่งนั้นเหรอ? :)
Drew Noakes

5
อ่านความคิดเห็นเหล่านี้อีกครั้งฉันต้องการที่จะชี้ให้เห็นว่าความคิดเห็นของ @Thomas Levesque นั้นเป็นจริงในแนวทางที่สองที่ฉันแสดง การใช้ล้วนItemsControlจะลบแนวคิดการเลือกใด ๆ
Drew Noakes

1
วิธีการแก้ปัญหา ItemsControl ลบออกสนับสนุนการเลื่อนกล่อง (แถบเลื่อนและล้อเลื่อน)
MuiBienCarlota

1
+1 สำหรับวิธีการ 1 - ItemsControl ถ้าเรามีหน้าขนาดใหญ่ที่เราต้องเลื่อนถ้าผู้ใช้เลื่อนเมาส์ไปบนกล่องรายการมันจะปิดการใช้งาน MouseWheel ได้อย่างมีประสิทธิภาพเมื่อกล่องรายการคว้าเหตุการณ์ MouseWheel ซึ่งหมายความว่าผู้ใช้จะรู้สึกหงุดหงิดที่ mousewheel ที่ใช้ในการเลื่อนหน้าทั้งหมดจะหยุดทำงานแบบสุ่มโดยขึ้นอยู่กับว่าเมาส์อยู่เหนือกล่องรายการหรือไม่
Contango

159

ฉันพบวิธีแก้ปัญหาที่ง่ายและตรงไปตรงมาทำงานให้ฉันฉันหวังว่ามันจะทำเพื่อคุณเช่นกัน

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

ฉันคิดว่าเขาผ่านมันค่อนข้างดีที่นี่: asaddurrani.wordpress.com/tag/wpf-listbox-disable-selection
Sid

3
มันสมบูรณ์แบบ มันป้องกันรายการที่เลือกและตัวควบคุมอื่น ๆ เช่นปุ่มยังใช้งานได้ สิ่งที่ฉันกำลังมองหา
Franck

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

ยอดเยี่ยม วิธีการที่คล้ายกันก็ใช้งานได้สำหรับฉันเมื่อฉันต้องการปุ่มบนไอเท็มที่จะไม่ทำให้เกิดการเลือกไอเท็ม - แต่เฉพาะเมื่อพื้นที่อื่น ๆ ของไอเท็มถูกคลิก เพียงตั้งปุ่มFocusable = "False"!
Jony Adamit

1
เพิ่มคุณสมบัติเพิ่มเติมนี้เพื่อลบการวางเมาส์โอเวอร์ที่ไฮไลต์เช่นกัน: <Setter Property="IsHitTestVisible" Value="False" />
DonBoitnott

25

คุณสามารถสลับไปใช้แทนItemsControl มีแนวคิดของการเลือกไม่ดังนั้นไม่มีอะไรที่จะปิดเป็นListBoxItemsControl


2
สวยงาม ฉันไม่เคยรู้เลยว่าคุณสามารถประกาศ ItemsControl ได้โดยตรงฉันคิดว่ามันเป็นเสมือนจริง (MustOverride) ขอบคุณ !!!
Shimmy Weitzhandler

แต่ ItemsControl จะยังคงแสดงรายการของฉันในหนึ่งบรรทัดหรือไม่
Chry Cheng

@Chry ItemTemplateใช่มันจะและนอกจากนี้คุณสามารถตั้งค่าด้วยตนเอง
Shimmy Weitzhandler

2
สิ่งนี้ทำให้สูญเสียฟังก์ชันการทำงานมากเกินไปเช่นการเลื่อน
เจฟฟ์

@Jeff คุณสามารถห่อ ItemsControl ใน ScrollViewer เพื่อรับการเลื่อน
Wilka

12

ตัวเลือกอื่นที่ควรพิจารณาคือปิดการใช้งาน ListBoxItems สิ่งนี้สามารถทำได้โดยการตั้งค่า ItemContainerStyle ดังแสดงในตัวอย่างต่อไปนี้

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

หากคุณไม่ต้องการให้ข้อความเป็นสีเทาคุณสามารถระบุสีที่ปิดใช้งานได้โดยเพิ่มแปรงลงในทรัพยากรของสไตล์ด้วยปุ่มต่อไปนี้: {x: Static SystemColors.GrayTextBrushKey} โซลูชันอื่นจะแทนที่แม่แบบการควบคุม ListBoxItem


ง่ายและทำงานได้ดีขอบคุณ! และมันใช้กับ WP 8.1 Runtime ได้เช่นกัน
Malutek

8

สิ่งนี้จะใช้งานได้หากฉันต้องการใช้กล่องรายการแทน itemscontrol แต่ฉันกำลังแสดงรายการที่ไม่ควรเลือกได้ฉันใช้:

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

3

คำตอบที่ดีค่อนข้างที่นี่ แต่ฉันกำลังมองหาบางสิ่งที่แตกต่างออกไปเล็กน้อย: ฉันต้องการการเลือก แต่ไม่ต้องการให้แสดง (หรือแสดงในเรื่องอื่น)

การแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน (สมบูรณ์) ดังนั้นฉันจึงทำอย่างอื่น: ฉันใช้รูปแบบใหม่สำหรับกล่องรายการของฉันซึ่งกำหนดแม่แบบใหม่ทั้งหมด:

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

เริ่มต้นด้วยสิ่งนั้นคุณสามารถเพิ่มการเน้นตัวเลือกของคุณเองหรือปล่อยไว้อย่างนั้นถ้าคุณไม่ต้องการอะไรเลย


2

ในขณะที่คำตอบของ @Drew Noakes เป็นทางออกที่รวดเร็วสำหรับกรณีส่วนใหญ่มีข้อบกพร่องเล็กน้อยที่มาพร้อมกับการตั้งค่า x: แปรงแบบคงที่

เมื่อคุณตั้งค่า x: แปรงแบบคงที่ตามที่แนะนำตัวควบคุมลูกทั้งหมดภายในรายการกล่องรายการจะได้รับลักษณะนี้

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

ตัวอย่างเช่นถ้าคุณมี ComboBox ภายใน ListBoxItem ของคุณมันจะปิดการใช้งานเมาส์เหนือการเน้นภายใน ComboBox

แต่พิจารณาตั้ง VisualStates สำหรับการเลือกเหตุการณ์ที่ไม่ได้เลือกและ MouseOver เป็นครอบคลุมในการแก้ปัญหาดังกล่าวในหัวข้อ StackOverflow นี้: ลบ Control Highlight จาก ListBoxItem แต่ไม่ควบคุมเด็ก

-Frinny


2

ฉันเสนอวิธีแก้ปัญหาอื่น เพียงแค่สร้างเทมเพลตใหม่ListBoxItemเพื่อไม่ContentPresenterให้เป็น ...

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

เหตุผลของฉันสำหรับวิธีนี้มีดังนี้:

  1. ในกรณีของฉันฉันไม่ต้องการปิดการใช้งานการโต้ตอบกับผู้ใช้กับเนื้อหาของฉันListBoxItemsดังนั้นการตั้งค่าIsEnabledจะไม่ทำงานสำหรับฉัน

  2. โซลูชันอื่นที่พยายามจัดรูปแบบใหม่ListBoxItemโดยการแทนที่คุณสมบัติที่เกี่ยวข้องกับสีจะทำงานเฉพาะกับอินสแตนซ์เหล่านั้นซึ่งคุณมั่นใจว่าแม่แบบนั้นใช้คุณสมบัติเหล่านั้น ไม่เป็นไรสำหรับรูปแบบเริ่มต้น แต่แบ่งกับสไตล์ที่กำหนดเอง

  3. การแก้ปัญหาที่ใช้ItemsControlสิ่งอื่น ๆ แบ่งมากเกินไปในขณะที่ItemsControlมีรูปลักษณ์ที่แตกต่างอย่างสิ้นเชิงกว่ามาตรฐานListBoxและไม่สนับสนุนการทำงานแบบเสมือนซึ่งหมายความว่าคุณต้องอีกครั้งแม่แบบItemsPanelอยู่แล้ว

ข้างต้นจะไม่เปลี่ยนรูปลักษณ์เริ่มต้นของListBoxไม่ปิดใช้งานรายการในเทมเพลตข้อมูลสำหรับListBoxสนับสนุนการจำลองเสมือนโดยค่าเริ่มต้นและทำงานโดยไม่ขึ้นกับสไตล์ใดก็ตามที่อาจมีหรือไม่มีการใช้งานในแอปของคุณ มันเป็นหลักการจูบ


1

หมายเหตุ: วิธีนี้จะไม่ปิดใช้งานการเลือกโดยการนำทางด้วยแป้นพิมพ์หรือคลิกขวา (เช่นปุ่มลูกศรตามด้วยปุ่มเว้นวรรค)

คำตอบก่อนหน้านี้ทั้งหมดลบความสามารถในการเลือกอย่างสมบูรณ์ (ไม่มีการสลับในรันไทม์) หรือเพียงแค่ลบเอฟเฟกต์ภาพ แต่ไม่ใช่การเลือก

แต่ถ้าคุณต้องการให้สามารถเลือกและแสดงรายการที่เลือกตามรหัส แต่ไม่ใช่จากการป้อนข้อมูลของผู้ใช้ คุณอาจต้องการ "หยุด" การเลือกของผู้ใช้ในขณะที่ไม่ปิดการใช้งานกล่องรายการทั้งหมดหรือไม่

วิธีแก้คือห่อทั้ง ItemsContentTemplate ให้เป็นปุ่มที่ไม่มีโครเมียมแบบภาพ ขนาดของปุ่มจะต้องเท่ากับขนาดของรายการดังนั้นจึงครอบคลุมอย่างสมบูรณ์ ตอนนี้ใช้คุณสมบัติ IsEnabled ของปุ่ม:

เปิดใช้งานปุ่มเพื่อ "หยุด" สถานะการเลือกของรายการ วิธีนี้ใช้งานได้เนื่องจากปุ่มเปิดใช้งานจะกินเหตุการณ์ของเมาส์ทั้งหมดก่อนที่จะเพิ่มรายการไปยัง ListboxItem-Eventhandler ItemsDataTemplate ของคุณจะยังคงรับ MouseEvents เนื่องจากเป็นส่วนหนึ่งของเนื้อหาปุ่ม

ปิดใช้งานปุ่มเพื่อเปิดใช้งานการเปลี่ยนแปลงการเลือกโดยคลิก

<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


1

บางทีคุณอาจต้องการฟังก์ชั่นเฉพาะของ ItemsControl? ไม่อนุญาตให้เลือก:

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

3
@Shimmy: มันเป็นเรื่องธรรมดาที่คำตอบเล็กน้อยจะเหมือนกัน ไม่มีการทำซ้ำที่นี่คุ้มค่าของธงใด ๆ หากคุณมีคำถามใด ๆ เพิ่มเติมเกี่ยวกับเรื่องนี้กรุณาสอบถามได้ที่Meta กองมากเกิน

0

คุณสามารถวาง Textblock ด้านบนกล่องรายการของคุณมันจะไม่เปลี่ยนรูปลักษณ์ของแอปพลิเคชันของคุณและจะไม่อนุญาตให้เลือกรายการใด ๆ


1
แม้ว่าคุณจะยังคงต้องปิดใช้งานการนำทางแท็บ
Amanduh

0

อินสแตนซ์ของการแก้ไขอย่างง่าย ๆ ที่ทำงานบน Windows Phone นั้นอยู่ที่การเลือกรายการที่เลือกเป็นค่าว่าง:

    <ListBox SelectionChanged="ListBox_SelectionChanged">

และในรหัสที่อยู่เบื้องหลัง:

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

0

ฉันพบวิธีที่สมบูรณ์แบบ
ชุดกล่องรายการ IsHitTestVisible เป็นเท็จเพื่อให้ผู้ใช้ไม่สามารถเลื่อนเมาส์หรือเลื่อนลงหรือเลื่อนขึ้น
จับภาพ PreviewGotKeyboardFocus e.Handled = true เพื่อให้ผู้ใช้สามารถเลือกรายการด้วยแท็บแป้นพิมพ์ลูกศรขึ้นลูกศรลง

วิธีนี้ได้เปรียบ:

  1. รายการกล่องรายการเบื้องหน้าจะไม่กลายเป็นสีเทา
  2. พื้นหลังกล่องรายการสามารถตั้งค่าเป็นโปร่งใส

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>

รหัส

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

-1

สำหรับฉันทางออกที่ดีที่สุดคือ:

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

-3

IsEnabled = false


2
มันทำให้เป็นสีเทาทั้งหมดนี่ไม่ใช่สิ่งที่ฉันกำลังมองหา
Shimmy Weitzhandler

1
แต่มันก็เป็นคำตอบที่ตรงไปตรงมาคำถามที่ตรงไปตรงมา :)
วิคเตอร์ Jevdokimov

1
คำตอบที่ตรงไปตรงมาคือstackoverflow.com/questions/1398559/1398650#1398650แต่ต้องขอบคุณต่อไป
Shimmy Weitzhandler

ช่วยมากสำหรับฉันฉันต้องการสีเทาและปิดการใช้งาน!
Martin Robins

-3

หากต้องการปิดการใช้งานหนึ่งตัวเลือกขึ้นไปใน listbox / dropdown ของคุณคุณสามารถเพิ่มแอตทริบิวต์ "disabled" ตามที่แสดงด้านล่าง วิธีนี้ป้องกันผู้ใช้จากการเลือกตัวเลือกนี้และได้รับการซ้อนทับสีเทา

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

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