Radiobuttons Ischecked 属性在 wpf mvvm 中不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12142337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 05:06:51  来源:igfitidea点击:

Radiobuttons Ischecked property is not working in wpf mvvm

wpfmvvm

提问by user1105705

I am unable to bind two radiobuttons to my xaml form and IsChecked property with same group names for which I also used nullabletoboolconverters. however, the radiobuttons ischecked property does not get changed in my code(it is not at all hitting the breakpoint, once we hit the first radiobutton after second one) and I am binding ischecked properties of two of them seperately as I need to set the visibility of some other panel on the form based on the radiobuttons property.

我无法使用相同的组名将两个单选按钮绑定到我的 xaml 表单和 IsChecked 属性,我也使用了 nullabletoboolconverters。但是,radiobuttons ischecked 属性在我的代码中没有改变(它根本没有到达断点,一旦我们在第二个单选按钮之后点击第一个单选按钮)并且我分别绑定其中两个的 ischecked 属性,因为我需要设置基于单选按钮属性的表单上其他一些面板的可见性。

the following is my xaml code and later is my viewmodel.cs code for radiobutton properties:

以下是我的 xaml 代码,后来是我的单选按钮属性的 viewmodel.cs 代码:

   <RadiobuttonSelectedConverter x:Key="CheckedSelection"/>// declaring my converter class in my resource dictionary.

  <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="3" Margin="10,5,0,0">
        <RadioButton GroupName="RadiosGroup" IsChecked="{Binding IsRadioButton1,Mode=TwoWay,
             Converter={StaticResource CheckedSelection}, ConverterParameter=true}">
                    First</RadioButton>
        <RadioButton GroupName="RadiosGroup" 
                     Margin="40,0,0,0" IsChecked="{Binding IsRadioButton2,Mode=TwoWay, 
            Converter={StaticResource CheckedSelection}, ConverterParameter=true}">Second</RadioButton>
    </StackPanel>



    private bool _isRadioButton1;

    public bool IsRadioButton1
    {
        get
        {
            return _isRadioButton1;
        }
        set
        {
            if _isRadioButton1!= value)
            {
                _isRadioButton1= value;

                IsRadioButton2= false;
                OnPropertyChanged("IsRadioButton1");

            }
        }
    }


    private bool _isRadioButton2;

    public bool IsRadioButton2
    {
        get
        {
            return _isRadioButton2;
        }
        set
        {
            if (_isRadioButton2 != value)
            {
                _isRadioButton2 = value;

              IsRadioButton1= false;
              OnPropertyChanged("IsRadioButton2");

            }
        }
    }

the following is my Converter code:

以下是我的转换器代码:

  [ValueConversion(typeof(bool?), typeof(bool))]
public class RadiobuttonSelectedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool param = bool.Parse(parameter.ToString());
        if (value == null)
        {
            return false;
        }
        else
        {
            return !((bool)value ^ param);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool param = bool.Parse(parameter.ToString());
        return !((bool)value ^ param);
    }
}

Someone please help me resolving my issue thanks in advance..

有人请帮我解决我的问题提前谢谢..

回答by Rachel

Personally I wouldn't code associated RadioButtonslike this at all. Since the selection behavior you want is the same used for a ListBox, I find it easiest to simply use a ListBoxthat is styled to use RadioButtonsfor each item.

就我个人而言,我根本不会RadioButtons像这样关联代码。由于您想要的选择行为与 a 所用的相同ListBox,我发现简单地使用 aListBox是最容易的,该 a样式RadioButtons用于每个项目。

The code-behind typically will contain

代码隐藏通常包含

  • ObservableCollection<string> Options
  • string SelectedOption
  • ObservableCollection<string> Options
  • string SelectedOption

and I will use this style for the ListBox:

我将使用这种风格ListBox

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

The style is applied like this:

样式应用如下:

<ListBox ItemsSource="{Binding Options}"
         SelectedValue="{Binding SelectedOption}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

You can also use something else instead of a Stringfor the collection, such as a ChildViewModel, then set your related View based on the current item, which means you don't have to bother with the Visibilityof the associated panel in your ViewModeleither.

您还可以为String集合使用其他东西而不是 a ,例如 a ChildViewModel,然后根据当前项目设置相关的 View ,这意味着您不必费心处理Visibility相关面板中的ViewModel

<DockPanel>
    <ListBox ItemsSource="{Binding OptionViewModels}"
             SelectedValue="{Binding SelectedViewModel}"
             Style="{StaticResource RadioButtonListBoxStyle}"
             DockPanel.Dock="Left">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding DisplayName}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <ContentControl Content="{Binding SelectedViewModel}" />
</DockPanel>

But as for your actual problem, I can think of 3 reasons it might be behaving incorrectly.

但至于您的实际问题,我可以想到 3 个可能行为不正确的原因。

The first is outlined in Jay's answer: you are setting IsChecked2to false in your setter for IsChecked1, and IsChecked2sets IsChecked1to false in its setter, so the end result is both values are false.

第一个在Jay 的回答中概述:您IsChecked2在 setter for中设置为 false IsChecked1,并在其 setter 中IsChecked2设置IsChecked1为 false,因此最终结果是两个值都为 false。

The second is it might be a problem with your converter. You said it a comment it was working correctly without the converter, so I think that may be part of the problem.

第二个是你的转换器可能有问题。你说这是一个评论,它在没有转换器的情况下正常工作,所以我认为这可能是问题的一部分。

And last of all, I believe changing grouped RadioButtonswill trigger an IsOptionA.IsSelected = falsefor the old item and an IsOptionB.IsSelected = truefor the newly selected item, and its possible those two are getting crossed somewhere.

最后,我相信更改分组RadioButtons将触发IsOptionA.IsSelected = false旧项目和IsOptionB.IsSelected = true新选择项目的一个,并且这两个可能在某处交叉。

回答by Jay

A couple of issues here.

这里有几个问题。

  1. You don't need a converter. Make IsRadioButton1and IsRadioButton2properties of type bool?, and the TwoWayBindingwill suffice, or just leave it as boolif tri-state is not applicable for you.
  2. The logic in your setters appears to be incorrect. In both cases, you are setting the value of the other RadioButtonto false, so if IsRadioButton1is trueand you then set IsRadioButton2to true, the setter will call IsRadioButton = false, and then that setter will call IsRadioButton2 = false. They will both end up being false.
  1. 你不需要转换器。makeIsRadioButton1IsRadioButton2type 的属性bool?,并且TwoWayBinding将就足够了,或者只是将其保留为bool好像三态不适用于您一样。
  2. 您的 setter 中的逻辑似乎不正确。在这两种情况下,您都将另一个的值设置RadioButtonfalse,因此如果IsRadioButton1true,然后您将其设置IsRadioButton2true,则设置器将调用IsRadioButton = false,然后该设置器将调用IsRadioButton2 = false。他们最终都会成为false.

You probably want this to read if(value) IsRadioButton2 = false;

你可能想读这个 if(value) IsRadioButton2 = false;



edit

编辑

Actually, as I recall, RadioButtonis not meant to be bound to a boolproperty the way a CheckBoxis. I think you bind all of the RadioButtons to one property, and use a Converterwith a ConverterParameterto set the property. I'll find an example and post in a minute.

实际上,我记得,RadioButton并不意味着bool像 a 那样绑定到属性CheckBox。我认为您将所有RadioButtons绑定到一个属性,并使用 aConverter和 aConverterParameter来设置该属性。我会找到一个例子并在一分钟内发布。



Okay, here is one solution, using a derived RadioButtonclass that behaves purely with bindings: http://blogs.msdn.com/b/mthalman/archive/2008/09/04/wpf-data-binding-with-radiobutton.aspx

好的,这是一个解决方案,使用一个RadioButton纯粹与绑定行为的派生类:http: //blogs.msdn.com/b/mthalman/archive/2008/09/04/wpf-data-binding-with-radiobutton.aspx

Here is a related SO question & answers: MVVM: Binding radio buttons to a view model?

这是一个相关的 SO 问答:MVVM:将单选按钮绑定到视图模型?