Як змусити групу перемикачів діяти як радіо кнопки у 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: Ви б хотіли детальніше пояснити, чому б ні? Це не яскравий приклад того, як використовувати шаблон елемента?
АБО Mapper

4
Це поганий приклад, оскільки ви плутаєте дисплей та поведінку. Ви змінюєте дисплей за допомогою шаблону даних, але у вас все ще є поведінка списку, а не поведінка набору кнопок радіо / тумблера. Взаємодія клавіатури дивна. Кращим рішенням може стати ItemControl з RadioButtons, оформлений як ToggleButtons (див. Іншу найвищу відповідь).
Зарат

Навіщо винаходити колесо?
Воблери

300

На мою думку, це найпростіший спосіб.

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

Насолоджуйтесь! - Пріксав


29
Ця відповідь повинна бути обраною на сьогоднішній день. Надає всі переваги радіо кнопки без недоліків прив'язки до якогось контролера. Я спершу спробував прив’язати до окремого набору невидимих ​​радіо кнопок, але це було непотрібне накладне покриття, і в результаті виникла помилка, де всі натиснуті кнопки виглядали виділеними, але не обов'язково перевіреними.
Лі Лув'є

16
Або, якщо вам потрібно застосувати це до всіх RadioButtons всередині елемента (наприклад, a Grid), використовуйте <Grid.Resources> <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}" /> </Grid.Resources>.
Роман Старков

16
один недолік цього способу полягає в тому, що ви не можете зняти прапорець, натиснувши на галочку.
Жульєн

2
Чи можна якось користувальницький стиль використовувати на такій кнопці?
wondra

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>

це працює для мене, насолоджуйтесь!


Я знаю, це не питання. Але що робити, якщо кнопка повинна вести себе як радіо кнопки, де її потрібно завжди обирати?
Карстен

На мою відповідь моє власне питання: прочитайте відповідь Удай Кірана :-)
Карстен

Приємно, що ця дія є такою ж, як кнопка "Переключити". Клацніть, щоб перевірити, і натисніть на цю ж кнопку, щоб зняти прапорець і коли я кладу всі RadioButtons в одну групу, вона діє як кнопки Radio. Дякую РоКК !!!
мілі

2
Це хороше рішення. Однак, коли у нас є подія. вона буде називатися двічі.
Хіем-Кім Хо Сюан

Якщо додати вміст, інший, ніж простий рядок, я отримаю "Елемент - це вже дочірній елемент іншого елемента". помилка. Чи існує спосіб цього?
Тобіас Хофер

5

ви завжди можете використовувати загальну подію на клавіші Click the ToggleButton, яка встановлює всі ToggleButton.IsChecked in groupcontrol (Grid, WrapPanel, ...) to false за допомогою 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

ви можете помістити в нього сітку з радіо кнопками та створити кнопку, схожу на шаблон для радіоустановок. ніж просто програматично видалити перевірку, якщо ви не хочете, щоб кнопки перемикалися


Але за допомогою радіо кнопок існує спосіб зняти виділення всіх кнопок? Після вибору я не бачу простого способу скасувати вибір!
code-zoop

RadioButton має властивість IsChecked, ви можете встановити його на помилковий код у разі необхідності
Арсен Мкртчян

2

Ви також можете спробувати System.Windows.Controls.Primitives.ToggleButton

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

Потім напишіть код проти IsCheckedвластивості, що імітує ефект радіобудівництва

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

Це не дуже загальнодоступне та багаторазове використання, наприклад, воно не використовується у ListBoxItems.
ANeves

0

Я робив це для RibbonToggleButtons, але, можливо, це те саме для звичайних ToggleButtons.

Я прив’язав IsChecked для кожної кнопки до значення перерахунку "mode", використовуючи EnumToBooleanConverter звідси. Як прив'язати RadioButtons до enum? (Вкажіть значення перерахунку для цієї кнопки за допомогою ConverterParameter. У вас має бути одне значення перерахунку для кожної кнопки)

Тоді для запобігання зняття галочки з кнопки, яка вже була перевірена, введіть це у свій код позаду події Click для кожної кнопки 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;
    }
}

Потім ви можете використовувати його, як запропонував Удай Кіран ...

<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, а також дозволяє UnChecking.


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}}">
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.