web-dev-qa-db-ja.com

WPF(MVVM)のラジオボタンのチェックを外す方法

ラジオボタングループがあります。フォームに記入するための選択は必須ではありません。最初は、すべてのラジオボタンがオフになっています。ユーザーが意図せずにそれらの1つをクリックした場合、少なくとも1つをチェックする必要があるため、戻ることはできません。

では、どうすればラジオボタンのチェックを外して、ユーザーに不要な選択を強制しないようにできますか?

p.s.フォームは実行時に作成され、MVVMデザインパターンに従っています。必須の選択の場合、ラジオボタンソリューションは非常によく適合し、この場合はすでに使用しています。

10
overcomer

個人的にこの動作が必要な場合は、ListBoxを使用するようにテンプレートを上書きしてRadioButtonsを使用します。

これは、次のすべてを実行するのに適した最適なコントロールです。

  • アイテムのリストを表示する
  • 一度に選択できるアイテムは1つだけなので、データモデルで維持されるプロパティは1つだけです。
  • ユーザーは、選択したアイテムをnullのままにして、アイテムが選択されていないことを示すことができます

ListBoxのカスタムスタイルは、境界線と背景色を削除し、RadioButtonListBoxItem.IsSelectedにバインドしてIsCheckedを使用して各アイテムを描画します。通常、次のようなものです。

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

そして、ラジオボタン自体を表示することは、通常、次のように非常に単純なことです。

<ListBox ItemsSource="{Binding AvailableValues}"
         SelectedValue="{Binding SelectedValue}"
         Style="{StaticResource RadioButtonListBoxStyle}" />
8
Rachel

これを試して:

public class OptionalRadioButton : RadioButton
{
    #region bool IsOptional dependency property
    public static DependencyProperty IsOptionalProperty = 
        DependencyProperty.Register(
            "IsOptional", 
            typeof(bool), 
            typeof(OptionalRadioButton), 
            new PropertyMetadata((bool)true,
                (obj, args) =>
                {
                    ((OptionalRadioButton)obj).OnIsOptionalChanged(args);
                }));
    public bool IsOptional
    {
        get
        {
            return (bool)GetValue(IsOptionalProperty);
        }
        set
        {
            SetValue(IsOptionalProperty, value);
        }
    }
    private void OnIsOptionalChanged(DependencyPropertyChangedEventArgs args)
    {
        // TODO: Add event handler if needed
    }
    #endregion

    protected override void OnClick()
    {
        bool? wasChecked = this.IsChecked;
        base.OnClick();
        if ( this.IsOptional && wasChecked == true )
            this.IsChecked = false;
    }
}
11
Peter Moore

このシナリオでは、いくつかのイベントハンドラーを使用しました

<RadioButton Checked="RB_Checked" Click="RB_Clicked"/>

XAMLの背後にあるコード:

Private JustChecked as Boolean

Private Sub RB_Checked(sender As Object, e As RoutedEventArgs)
    Dim s As RadioButton = sender
    ' Action on Check...
    JustChecked = True
End Sub

Private Sub RB_Clicked(sender As Object, e As RoutedEventArgs)
    If JustChecked Then
        JustChecked = False
        e.Handled = True
        Return
    End If
    Dim s As RadioButton = sender
    If s.IsChecked Then s.IsChecked = False        
End Sub

またはC#で

private bool JustChecked;
private void RB_Checked(object sender, RoutedEventArgs e)
{
    RadioButton s = sender;
    // Action on Check...
    JustChecked = true;
}

private void RB_Clicked(object sender, RoutedEventArgs e)
{
    if (JustChecked) {
        JustChecked = false;
        e.Handled = true;
        return;
    }
    RadioButton s = sender;
    if (s.IsChecked)
        s.IsChecked = false;
}

[チェックされたイベントの後にイベントが発生する]をクリックします

6
dba

汚い方法は、折りたたまれたラジオボタンを作成することです

<StackPanel>
    <RadioButton Content="Option 1" GroupName="optionSet1" PreviewMouseDown="RadioButton_OnPreviewMouseDown"/>
    <RadioButton Content="Option 2" GroupName="optionSet1" PreviewMouseDown="RadioButton_OnPreviewMouseDown"/>
    <RadioButton GroupName="optionSet1" x:Name="rbEmpty" Visibility="Collapsed" />
</StackPanel>

また、ユーザーがすでにチェックされているRadioButtonをクリックした場合は、空のRadioButtonをチェックします。

背後にあるコード

private void RadioButton_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        var radioButton = sender as RadioButton;
        if (radioButton.IsChecked.GetValueOrDefault())
        {
            rbEmpty.IsChecked = true;
            e.Handled = true;
        }
    }
1
Bohdan Biehov

ラジオボタン:

<RadioButton x:Name="MyRadioButton">Some Radio Button</RadioButton>

コードビハインド:

 MyRadioButton.IsChecked = false;

バインディングを使用してチェックを外したい場合は、次のようにします。

背後にあるコード:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = this;

    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    #endregion


    private bool _isRadioChecked;

    public bool IsRadioChecked
    {
        get
        {
            return _isRadioChecked;
        }
        set
        {
            _isRadioChecked = value;
            OnPropertyChanged("IsRadioChecked");
        }
    }
}

xaml(表示):

<RadioButton IsChecked="{Binding IsRadioChecked}">Some Radio Button</RadioButton>
1
Tono Nam

@Tomtomが指摘したように、チェックボックスを使用することもできますが、同時に複数のオプションをチェックする機会も与えられますまたは一度に1つのオプションのみがチェックされるようにするには、複雑なメカニズムを実装する必要があります。

もう1つの非常に安価な回避策は、ラジオボタンの選択肢にエントリを追加することです。

どうやって私たちのことを知りましたか?

  • グーグル
  • 友達
  • テレビの広告
  • その他
0
Fabio Salvalai

これは答えが少し遅いことは知っていますが、UWPを使用しても同様の問題が発生し、これが役立つかもしれないと思いました。ユーザーがオプションを選択および選択解除できるカスタムメニューを開発していました。私のソリューションは次のテストコードに示されています。

メインページXaml:

<Grid>
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <RadioButton x:Name="RB1" GroupName="RBTest" Content="Item No. 1" Click="RBtn_Click"/>
        <RadioButton x:Name="RB2" GroupName="RBTest" Content="Item No. 2" Click="RBtn_Click"/>
        <RadioButton x:Name="RB3" GroupName="RBTest" Content="Item No. 3" Click="RBtn_Click"/>
        <RadioButton x:Name="RB4" GroupName="RBTest" Content="Item No. 4" Click="RBtn_Click"/>
        <RadioButton x:Name="RB5" GroupName="RBTest" Content="Item No. 5" Click="RBtn_Click"/>
    </StackPanel>
</Grid>

背後にあるメインページのコード:

public sealed partial class MainPage : Page
{
    private bool rb1PrevState;
    private bool rb2PrevState;
    private bool rb3PrevState;
    private bool rb4PrevState;
    private bool rb5PrevState;

    public MainPage()
    {
        this.InitializeComponent();
        rb1PrevState = this.RB1.IsChecked.Value;
        rb2PrevState = this.RB2.IsChecked.Value;
        rb3PrevState = this.RB3.IsChecked.Value;
        rb4PrevState = this.RB4.IsChecked.Value;
        rb5PrevState = this.RB5.IsChecked.Value;

    }

    private void RBtn_Click(object sender, RoutedEventArgs e)
    {
        RadioButton rbtn = sender as RadioButton;

        if (rbtn != null)
        {
            if (rbtn.IsChecked.Value == true)
            {
                switch (rbtn.Name)
                {
                    case "RB1":
                        if (rb1PrevState == true)
                        {
                            rbtn.IsChecked = false;
                            rb1PrevState = false;
                        }
                        else
                        {
                            rb1PrevState = true;
                            ResetRBPrevStates("RB1");
                        }
                        break;
                    case "RB2":
                        if (rb2PrevState == true)
                        {
                            rbtn.IsChecked = false;
                            rb2PrevState = false;
                        }
                        else
                        {
                            rb2PrevState = true;
                            ResetRBPrevStates("RB2");
                        }
                        break;
                    case "RB3":
                        if (rb3PrevState == true)
                        {
                            rbtn.IsChecked = false;
                            rb3PrevState = false;
                        }
                        else
                        {
                            rb3PrevState = true;
                            ResetRBPrevStates("RB3");
                        }
                        break;
                    case "RB4":
                        if (rb4PrevState == true)
                        {
                            rbtn.IsChecked = false;
                            rb4PrevState = false;
                        }
                        else
                        {
                            rb4PrevState = true;
                            ResetRBPrevStates("RB4");
                        }
                        break;
                    case "RB5":
                        if (rb5PrevState == true)
                        {
                            rbtn.IsChecked = false;
                            rb5PrevState = false;
                        }
                        else
                        {
                            rb5PrevState = true;
                            ResetRBPrevStates("RB5");
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }

    private void ResetRBPrevStates(string _excludeRB)
    {
        rb1PrevState = (_excludeRB == "RB1" ? rb1PrevState : false);
        rb2PrevState = (_excludeRB == "RB2" ? rb2PrevState : false);
        rb3PrevState = (_excludeRB == "RB3" ? rb3PrevState : false);
        rb4PrevState = (_excludeRB == "RB4" ? rb4PrevState : false);
        rb5PrevState = (_excludeRB == "RB5" ? rb5PrevState : false);
    }
}

これは私にとってはうまく機能し、私に関する限り、MVVMルールに違反することはありません。

0
RobDev

こんにちはこれは、ラジオボタンをクリックするたびにチェックとチェックを外す方法です。

  int click = 0;
    private void RadioButton_Click(object sender, RoutedEventArgs e)
    {
        click++;
        ((RadioButton)sender).IsChecked = click % 2 == 1 ;
        click %= 2;
    }
0
luka

RadioButtonはおそらく最良の設計選択ではないというトムトムに同意しますが、その選択が制御できない場合、または他の理由で必要な場合は、選択解除を強制するメカニズムが必要になります。

ここにいくつかの可能性があります:

  • RadioButtonグループの近くにあるクリアボタン
  • もう一度クリックすると、すでにチェックされているRadioButtonの選択を解除します。
  • チェックされたRadioButtonが右クリックされたときに、コンテキストメニューの[クリア]オプションを提供します

フォームは実行時に作成されるため、コントロールを作成するときに、次のように適切なイベントハンドラーをアタッチする必要があります。

   // Create an instance of the control
   var controlType = typeof(Control).Assembly.GetType(fullyQualifiedControl, true);
   var control = Activator.CreateInstance(controlType);

    switch (fullyQualifiedControl)
    {
       case "System.Windows.Controls.RadioButton":
          ((RadioButton)control).Checked += new RoutedEventHandler(DataDrivenControl_Checked);
          ((RadioButton)control).Unchecked += new RoutedEventHandler(DataDrivenControl_UnChecked);
          break;
    }
0
Bobby