【问题标题】:How To Set The Correct RadioButton.IsChecked Property True By Binding To A ViewModel?如何通过绑定到 ViewModel 将正确的 RadioButton.IsChecked 属性设置为 True?
【发布时间】:2011-09-09 15:39:43
【问题描述】:

我有以下场景,其中一个类是这样的:

public class PetOwnerViewModel{
public PetOwnerStatus Status{get{return _petOwner.Status;}}

    public ICommand SetStatusCommand {get{...}}
}

一组RadioButtons的DataContext是否类似于这样:

<Parent DataContext="{Binding Path=PetOwner}" >
    <Parent.Resources>
        <myenums:PetOwnerStatus x:Key="CATLOVER">
            CatLover
        </myenums:PetOwnerStatus>
        <myenums:PetOwnerStatus x:Key="DOGLOVER">
            DogLover
        </myenums:PetOwnerStatus>
    </Parent.Resources>     
<StackPanel>
        <RadioButton Name="catLoverRadioButton"
                    Command="{Binding SetStatusCommand}"  
                CommandParameter="{StaticResource DOGLOVER}"
        GroupName="PetOwnerStatusRadioButtonGroup">
            Cat Lover
    </RadioButton>
        <RadioButton Name="dogLoverRadioButton"
                    Command="{Binding SetStatusCommand}"
                    CommandParameter="{StaticResource CATLOVER}"
        GroupName="SubjectStatusRadioButtonGroup" >
            Dog Lover
        </RadioButton>
    </StackPanel>
</Parent>

如何将 View 绑定到 ViewModel,以便如果 PetOwnerViewModel.Status 返回 PetOwnerStatus.CatLover,catLoverRadioButton.IsChecked 为 true。

【问题讨论】:

    标签: c# wpf xaml data-binding radio-button


    【解决方案1】:

    您可以使用数据模板使这种事情变得非常动态,例如

    (-- 编辑:使用已经具有SelectedItem 属性的ListBox 更有意义,请参阅this revised answer --)

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        //For simplicity in put everything in the Window rather than models and view-models
        public enum TestEnum { Ichi, Ni, San }
    
        private TestEnum _EnumValue;
        public TestEnum EnumValue
        {
            get { return _EnumValue; }
            set
            {
                if (_EnumValue != value)
                {
                    _EnumValue = value;
                    PropertyChanged.Notify(() => this.EnumValue);
                }
            }
        }
    
        //...
    }
    
    <ItemsControl>
        <ItemsControl.Resources>
            <!-- Gets the enum values -->
            <ObjectDataProvider x:Key="items" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
                <ObjectDataProvider.MethodParameters>
                    <x:Type TypeName="local:MainWindow+TestEnum" />
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
            <!-- A MultiValueConverter which compares for equality -->
            <vc:EqualityComparisonConverter x:Key="eqc" />
        </ItemsControl.Resources>
        <ItemsControl.ItemsSource>
            <Binding Source="{StaticResource items}" />
        </ItemsControl.ItemsSource>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <RadioButton Content="{Binding}" GroupName="TestEnumGroup"
                        Command="{x:Static local:Commands.DoStuff}" CommandParameter="{Binding}">
                    <RadioButton.IsChecked>
                        <MultiBinding Converter="{StaticResource eqc}" Mode="OneWay">
                            <!-- This should point to the viewmodel enum property -->
                            <Binding ElementName="Window" Path="DataContext.EnumValue" />
                            <!-- This passes the DataContext, the enum value behind the templated item, to the converter -->
                            <Binding />
                        </MultiBinding>
                    </RadioButton.IsChecked>
                </RadioButton>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    
    private void DoStuff_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        TestEnum enumval = (TestEnum)e.Parameter;
        EnumValue = enumval;
    }
    

    这使用原始枚举值进行操作,您可以使用属性通过显示友好的字符串来扩充它们。

    因为 IsChecked 绑定在所有 RadioButtons 上,所以 RadioButton.GroupName 变得多余。

    我没有提供EqualityComparisonConverter 的实现,因为它可能很垃圾,但正确实现它应该不会太难

    【讨论】:

    • 非常感谢,我已经在我的解决方案中实现了这一点,并且在可能的附加枚举值方面有一些灵活的东西会更好。
    • 这有点复杂,但对于更大的枚举确实有好处。很高兴它有帮助:)
    【解决方案2】:

    WPF 中有一个众所周知的错误,即数据绑定和 RadioButtons。这是我通常会这样做的方式:

    <StackPanel>
        <RadioButton
            Content="Cat Lover"
            Command="{Binding SetStatusCommand}"  
            CommandParameter="{x:Static local:PetOwnerStatus.CatLover}"
            IsChecked="{Binding Path=Status, Mode=TwoWay, Converter={StaticResource equalityConverter}, ConverterParameter={x:Static local:PetOwnerStatus.CatLover}}"
            GroupName="1" />
    
        <RadioButton
            Content="Dog Lover"
            Command="{Binding SetStatusCommand}"  
            CommandParameter="{x:Static local:PetOwnerStatus.DogLover}"
            IsChecked="{Binding Path=Status, Mode=TwoWay, Converter={StaticResource equalityConverter}, ConverterParameter={x:Static local:PetOwnerStatus.DogLover}}"
            GroupName="2" />
    </StackPanel>
    

    equalConverter 采用枚举的 ConverterParameter 并将其与绑定值(状态)进行比较。如果值相等,则转换器返回 true,进而将 IsChecked 设置为 true。上面的 IsChecked 绑定表达式本质上是说“如果 ConverterParameter 中指定的值等于 Status 的值,则将 IsChecked 设置为 true”。

    此外,您可以通过定义命名空间和使用 x:Static 来使用实际的枚举值,而无需创建单独的资源。

    请注意,您必须为每个 RadioButton 指定不同的 GroupName,否则 WPF 错误会自行显现并且绑定会被破坏。

    更多详情请点击此处: How to bind RadioButtons to an enum?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-28
      • 2013-12-05
      • 1970-01-01
      • 2011-08-26
      • 2023-03-02
      • 2011-01-22
      • 2015-11-24
      • 2011-08-01
      相关资源
      最近更新 更多