Làm cách nào để nhóm các nút bật tắt hoạt động giống như các nút radio trong WPF?


122

Tôi có một nhóm các nút hoạt động giống như các nút bật tắt, nhưng cũng như các nút radio nơi chỉ có thể chọn / nhấn một nút tại thời điểm hiện tại. Nó cũng cần phải có trạng thái không có nút nào được chọn / nhấn xuống.

Hành vi sẽ giống như thanh công cụ của Photoshop, nơi không hoặc một trong các công cụ được chọn bất cứ lúc nào!

Bất kỳ ý tưởng làm thế nào điều này có thể được thực hiện trong WPF?

Câu trả lời:


38

Cách dễ nhất là tạo kiểu cho ListBox để sử dụng ToggleButtons cho ItemTemplate của nó

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

Sau đó, bạn có thể sử dụng thuộc tính SelectionMode của ListBox để xử lý SingleSelect so với MultiSelect.


cảm ơn bạn đã chia sẻ! tôi đã tự hỏi liệu điều này là thực hành tốt ... nhưng nó có vẻ là ok ..
GorillaApe

1
@LeeLouviere: Bạn có muốn giải thích tại sao không? Đó không phải là một ví dụ điển hình về cách sử dụng mẫu mục sao?
HOẶC Mapper

4
Đó là một ví dụ tồi vì bạn nhầm lẫn giữa hiển thị và hành vi. Bạn thay đổi hiển thị thông qua datatemplate nhưng bạn vẫn có hoạt động của hộp danh sách chứ không phải hoạt động của một tập hợp các nút radio / nút bật tắt. Tương tác bàn phím thật kỳ lạ. Một giải pháp tốt hơn sẽ là một ItemsControl với RadioButtons, được tạo kiểu là ToggleButtons (xem câu trả lời được bình chọn cao nhất khác).
Zarat,

Tại sao phải phát minh lại bánh xe?
Wobbles

300

Đây là cách dễ nhất theo ý kiến ​​của tôi.

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

Thưởng thức! - Cưa sắt


29
Câu trả lời này nên được chọn cho đến nay. Cung cấp cho bạn tất cả các lợi ích của một nút radio mà không có nhược điểm của việc ràng buộc với một số bộ điều khiển. Lần đầu tiên tôi thử liên kết với bộ nút radio vô hình riêng biệt, nhưng điều đó có chi phí không cần thiết và cuối cùng dẫn đến lỗi trong đó tất cả các nút được nhấp vào trông được đánh dấu nhưng không nhất thiết phải được kiểm tra.
Lee Louviere

16
Hoặc, nếu bạn cần áp dụng điều này cho tất cả các RadioButtons bên trong một phần tử (ví dụ: a Grid), hãy sử dụng <Grid.Resources> <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}" /> </Grid.Resources>.
Roman Starkov

16
một nhược điểm của phương pháp này là bạn không thể bỏ chọn một nút radio bằng cách nhấp vào một nút đã chọn.
Julien

2
Có thể tùy chỉnh phong cách được sử dụng trên nút chuyển đổi như vậy bằng cách nào đó?
wonderra

2
@wondra Bạn chỉ có thể gán một kiểu duy nhất cho FrameworkElement. Tuy nhiên, bạn có thể điều chỉnh giải pháp romkyns và kế thừa từ phong cách 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>

nó hoạt động cho tôi, tận hưởng!


Tôi biết đây không phải là câu hỏi. Nhưng phải làm gì nếu nút phải hoạt động giống như các nút radio, nơi luôn phải chọn một nút?
Karsten

Để trả lời của tôi câu hỏi của riêng tôi: đọc câu trả lời của Uday Kiran :-)
Karsten

Tuyệt vời, điều này hoạt động giống như nút Chuyển đổi. Nhấp để kiểm tra và nhấp vào cùng một nút để bỏ chọn. và một khi tôi đặt tất cả các Nút Radio trong cùng một nhóm, nó hoạt động giống như các nút Radio. Cảm ơn RoKK !!!
mili

2
Đó là một giải pháp tốt. Tuy nhiên, khi chúng tôi có một sự kiện. nó sẽ được gọi hai lần.
Khiêm-Kim Hồ Xuân

Nếu thêm nội dung khác thì một chuỗi đơn giản tôi nhận được "Phần tử đã là con của phần tử khác." lỗi. Có cách nào giải quyết vấn đề này không?
Tobias Hoefer,

5

bạn luôn có thể sử dụng một sự kiện chung trong Nhấp chuột của ToggleButton đặt tất cả ToggleButton.IsChecked trong một điều khiển nhóm (Grid, WrapPanel, ...) thành false với sự trợ giúp của VisualTreeHelper; sau đó kiểm tra lại người gửi. Hoặc một cái gì đó tương tự như vậy.

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

bạn có thể đặt lưới với các nút radio và tạo nút giống như mẫu cho raduiobuttons. hơn là chỉ có lập trình, hãy xóa kiểm tra nếu bạn không muốn các nút được chuyển đổi


Nhưng bằng cách sử dụng các nút radio, có cách nào để bỏ chọn tất cả các nút không? Sau khi được chọn, tôi không thấy cách dễ dàng để bỏ chọn nó!
code-zoop

RadioButton có một tài sản IsChecked, bạn có thể thiết lập nó để sai trong mã khi bạn cần
Arsen Mkrtchyan

2

Bạn cũng có thể thử System.Windows.Controls.Primitives.ToggleButton

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

Sau đó viết mã dựa vào thuộc IsCheckedtính để bắt chước hiệu ứng nút radio

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

Điều này không phải là rất chung chung và có thể tái sử dụng ... ví dụ, nó không thể sử dụng được bên trong ListBoxItems.
ANeves

0

Tôi đã làm điều này cho RibbonToggleButtons, nhưng có lẽ nó cũng giống như đối với ToggleButtons thông thường.

Tôi đã liên kết IsChecked cho mỗi nút với một giá trị enum "mode" bằng EnumToBooleanConverter từ đây Làm cách nào để liên kết RadioButtons với một enum? (Chỉ định giá trị enum cho nút này bằng cách sử dụng ConverterParameter. Bạn nên có một giá trị enum cho mỗi nút)

Sau đó, để ngăn việc bỏ chọn một nút đã được chọn, hãy đặt nút này vào mã của bạn phía sau cho sự kiện Click cho mỗi 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

Để giúp những người như Julian và tôi (hai phút trước ...). Bạn có thể bắt nguồn từ những thứ RadioButtonnhư thế này.

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

Sau đó, bạn có thể sử dụng nó như Uday Kiran đã đề xuất ...

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

Phương pháp này chỉ có một phép ToggleButtonđược Checkedcùng một lúc, và nó cũng cho phép bỏ chọn.


0

Tôi lấy một vài câu trả lời và thêm một số mã bổ sung. Giờ đây, bạn có thể có các nhóm nút bật tắt khác nhau hoạt động giống như một nút bật tắt:

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

Và các nhóm nút radio khác nhau trông giống như các nút bật tắt:

<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}}">
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.