จะทำให้กลุ่มปุ่มสลับทำหน้าที่เหมือนปุ่มตัวเลือกใน WPF ได้อย่างไร


122

ฉันมีกลุ่มปุ่มที่ควรทำหน้าที่เหมือนปุ่มสลับ แต่ยังเป็นปุ่มตัวเลือกที่สามารถเลือก / กดลงได้เพียงปุ่มเดียวในเวลาปัจจุบัน นอกจากนี้ยังต้องมีสถานะที่ไม่มีการเลือก / กดปุ่มใด ๆ

ลักษณะการทำงานจะเป็นเหมือนแถบเครื่องมือ Photoshop โดยเลือกศูนย์หรือเครื่องมือใดเครื่องมือหนึ่งเมื่อใดก็ได้!

มีความคิดอย่างไรว่าสิ่งนี้สามารถนำไปใช้ใน WPF ได้หรือไม่?

คำตอบ:


38

วิธีที่ง่ายที่สุดคือจัดรูปแบบ ListBox เพื่อใช้ ToggleButtons สำหรับ ItemTemplate

<Style TargetType="{x:Type ListBox}">
    <Setter Property="ListBox.ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <ToggleButton Content="{Binding}" 
                              IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

จากนั้นคุณสามารถใช้คุณสมบัติ SelectionMode ของ ListBox เพื่อจัดการ SingleSelect vs MultiSelect


ขอบคุณสำหรับการแชร์! ฉันสงสัยว่านี่เป็นแนวทางปฏิบัติที่ดีหรือไม่ ... แต่ดูเหมือนว่าจะโอเค ..
GorillaApe

1
@LeeLouviere: คุณสนใจที่จะอธิบายอย่างละเอียดว่าทำไมไม่? นั่นเป็นตัวอย่างที่สำคัญของการใช้เทมเพลตรายการหรือไม่?
หรือผู้ทำแผนที่

4
เป็นตัวอย่างที่ไม่ดีเนื่องจากคุณสับสนในการแสดงผลและพฤติกรรม คุณเปลี่ยนการแสดงผลผ่าน datatemplate แต่คุณยังคงมีลักษณะการทำงานของ listbox และไม่ใช่ลักษณะการทำงานของชุดปุ่มวิทยุ / ปุ่มสลับ การโต้ตอบของแป้นพิมพ์เป็นเรื่องแปลก ทางออกที่ดีกว่าคือ ItemsControl with RadioButtons ซึ่งมีลักษณะเป็น ToggleButtons (ดูคำตอบที่ได้รับการโหวตสูงสุดอื่น ๆ )
Zarat

ทำไมต้องคิดค้นล้อใหม่?
ถล่ม

300

นี่เป็นวิธีที่ง่ายที่สุดในความคิดของฉัน

<RadioButton Style="{StaticResource {x:Type ToggleButton}}" />

สนุก! - เลื่อยยนต์


29
อันนี้ควรเลือกตอบโดยไกล ให้ประโยชน์ทั้งหมดของ radiobutton โดยไม่มีข้อเสียในการผูกมัดกับคอนโทรลเลอร์บางตัว ครั้งแรกฉันพยายามผูกมัดเพื่อแยกชุดปุ่มเรดิโอที่มองไม่เห็น แต่นั่นมีค่าใช้จ่ายที่ไม่จำเป็นและจบลงด้วยข้อผิดพลาดที่ปุ่มทั้งหมดที่คลิกดูไฮไลต์ แต่ไม่จำเป็นต้องตรวจสอบ
Lee Louviere

16
หรือหากคุณต้องการใช้สิ่งนี้กับ RadioButtons ทั้งหมดภายในองค์ประกอบ (เช่นกGrid) ให้ใช้<Grid.Resources> <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}" /> </Grid.Resources>.
Roman Starkov

16
ข้อเสียอย่างหนึ่งของวิธีนี้คือคุณไม่สามารถยกเลิกการเลือกปุ่มตัวเลือกโดยคลิกที่ปุ่มที่เลือกไว้
Julien

2
สามารถใช้สไตล์ที่กำหนดเองบนปุ่มสลับดังกล่าวได้หรือไม่?
มหัศจรรย์

2
@wondra คุณสามารถกำหนดสไตล์เดียวให้กับ FrameworkElement อย่างไรก็ตามคุณสามารถปรับใช้โซลูชัน romkyns และสืบทอดจากสไตล์ ToggleButton:<Style BasedOn="{StaticResource {x:Type ToggleButton}}" x:Key="Blubb" TargetType="RadioButton"><Setter Property="Background" Value="Yellow" /></Style>
Suigi

32
<RadioButton Content="Point" >
    <RadioButton.Template>
        <ControlTemplate>
            <ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                          Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
        </ControlTemplate>
    </RadioButton.Template>
</RadioButton>

มันได้ผลสำหรับฉันสนุก!


ฉันรู้ว่านี่ไม่ใช่คำถาม แต่จะทำอย่างไรถ้าปุ่มควรทำงานเหมือนปุ่มวิทยุที่ต้องเลือกเสมอ?
Karsten

เพื่อตอบคำถามของฉันเอง: อ่านคำตอบโดย Uday Kiran :-)
Karsten

ดีสิ่งนี้ทำหน้าที่เป็นปุ่ม SAME เป็นปุ่มสลับ คลิกเพื่อตรวจสอบและคลิกที่ปุ่มเดียวกันเพื่อยกเลิกการเลือก และเมื่อฉันใส่ RadioButtons ทั้งหมดไว้ในกลุ่มเดียวกันมันจะทำหน้าที่เหมือนปุ่มวิทยุ ขอบคุณ RoKK !!!
mili

2
นับเป็นทางออกที่ดี อย่างไรก็ตามเมื่อเรามีเหตุการณ์ มันจะถูกเรียกสองครั้ง
Khiem-Kim Ho Xuan

หากมีการเพิ่มเนื้อหาอื่น ๆ สตริงธรรมดาฉันจะได้รับข้อความ "Element เป็นลูกขององค์ประกอบอื่นอยู่แล้ว" ความผิดพลาด มีวิธีการนี้หรือไม่?
Tobias Hoefer

5

คุณสามารถใช้เหตุการณ์ทั่วไปบน Click of the ToggleButton ที่ตั้งค่า ToggleButton.IsChecked ทั้งหมดใน groupcontrol (Grid, WrapPanel, ... ) เป็นเท็จด้วยความช่วยเหลือของ VisualTreeHelper; จากนั้นตรวจสอบผู้ส่งอีกครั้ง หรือสิ่งที่ชอบในสิ่งนั้น

private void ToggleButton_Click(object sender, RoutedEventArgs e)
    {
        int childAmount = VisualTreeHelper.GetChildrenCount((sender as ToggleButton).Parent);

        ToggleButton tb;
        for (int i = 0; i < childAmount; i++)
        {
            tb = null;
            tb = VisualTreeHelper.GetChild((sender as ToggleButton).Parent, i) as ToggleButton;

            if (tb != null)
                tb.IsChecked = false;
        }

        (sender as ToggleButton).IsChecked = true;
    }

4

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


แต่การใช้ปุ่มตัวเลือกมีวิธียกเลิกการเลือกปุ่มทั้งหมดหรือไม่? เมื่อเลือกแล้วฉันไม่เห็นวิธีง่ายๆในการยกเลิกการเลือก!
code-zoop

RadioButton มีคุณสมบัติ IsChecked คุณสามารถตั้งค่าเป็นรหัสเท็จเมื่อคุณต้องการ
Arsen Mkrtchyan

2

คุณยังสามารถลอง System.Windows.Controls.Primitives.ToggleButton

 <ToggleButton Name="btnTest" VerticalAlignment="Top">Test</ToggleButton>

จากนั้นเขียนโค้ดเทียบกับIsCheckedคุณสมบัติเพื่อเลียนแบบเอฟเฟกต์ radiobutton

 private void btnTest_Checked(object sender, RoutedEventArgs e)
 {
     btn2.IsChecked = false;
     btn3.IsChecked = false;
 }

นี่ไม่ใช่เรื่องทั่วไปและใช้ซ้ำได้ ... ตัวอย่างเช่นไม่สามารถใช้งานได้ภายในListBoxItems
ANeves

0

ฉันทำสิ่งนี้สำหรับ RibbonToggleButtons แต่อาจจะเหมือนกันสำหรับ ToggleButtons ปกติ

ฉันผูก IsChecked สำหรับแต่ละปุ่มกับค่า enum "mode" โดยใช้ EnumToBooleanConverter จากที่นี่จะผูก RadioButtons กับ enum ได้อย่างไร (ระบุค่า enum สำหรับปุ่มนี้โดยใช้ ConverterParameter คุณควรมีค่า enum หนึ่งค่าสำหรับแต่ละปุ่ม)

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

    private void PreventUncheckRibbonToggleButtonOnClick ( object sender, RoutedEventArgs e ) {

        // Prevent unchecking a checked toggle button - so that one always remains checked
        // Cancel the click if you hit an already-checked button

        var button = (RibbonToggleButton)sender;
        if( button.IsChecked != null ) { // Not sure why checked can be null but that's fine, ignore it
            bool notChecked = ( ! (bool)button.IsChecked );
            if( notChecked ){ // I guess this means the click would uncheck it
                button.IsChecked = true; 
            }
        }
    }

0

เพื่อช่วยคนอย่างจูเลียนและฉัน (สองนาทีที่แล้ว ... ) คุณสามารถได้รับจากสิ่งRadioButtonนี้

class RadioToggleButton : RadioButton
{
    protected override void OnToggle()
    {
        if (IsChecked == true) IsChecked = IsThreeState ? (bool?)null : (bool?)false;
        else IsChecked = IsChecked.HasValue;
    }
}

จากนั้นคุณสามารถใช้มันได้ตามที่ Uday Kiran แนะนำ ...

<Window x:Class="Sample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Sample"
    Title="MainWindow" Height="600" Width="600">
    <StackPanel>
        <local:RadioToggleButton Content="Button" Style="{StaticResource {x:Type ToggleButton}}" />
    </StackPanel>
</Window>

วิธีการนี้จะช่วยให้เพียงคนเดียวToggleButtonที่จะเป็นCheckedในเวลาและมันยังช่วยให้ยกเลิกการเลือก


0

ฉันได้รับคำตอบสองสามคำและเพิ่มรหัสพิเศษ ตอนนี้คุณสามารถมีปุ่มสลับกลุ่มต่างๆซึ่งทำหน้าที่เหมือนปุ่มสลับปุ่มเดียว:

<UserControl.Resources>
    <Style x:Key="GroupToggleStyle" TargetType="ToggleButton">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding GroupName, RelativeSource={RelativeSource Self}}" Value="Group1"/>
                    <Condition Binding="{Binding BooleanProperty}" Value="true"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter Property="IsChecked" Value="true"/>
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

และกลุ่มต่างๆของปุ่มตัวเลือกที่มีลักษณะเหมือนปุ่มสลับ:

<Radio Button GroupName="Group1" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group1" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group2" Style="{StaticResource {x:Type ToggleButton}}">
<Radio Button GroupName="Group3" Style="{StaticResource {x:Type ToggleButton}}">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.