web-dev-qa-db-ja.com

WPF + MVVM + RadioButton:単一のプロパティでバインディングを処理します

SOおよびインターネット上の他の多くの資料に関する this および this (およびその他の)質問から、ラジオボタンをVMにバインドする方法を理解しました。

ただし、それらはすべて、ラジオボタンの可能な値ごとに個別のプロパティを作成します。 1つの質問( this )は私の要件に似ていますが、受け入れられた回答は、ラジオボタンの代わりにリストボックスを使用することを提案しています。

人の性別(データ型CHAR、可能な値 'M'、 'F')を表すには、VM as PersonGender、IsPersonMale、IsPerson Femaleとして3つのプロパティを作成する必要があります。 1つのプロパティPersonGender。これを行うことはできますか?はいの場合、どのように?

9
Amit Joshi

コンバーターが必要です。

//define this in the Window's Resources section or something similiarly suitable
<local:GenderConverter x:Key="genderConverterKey" />


<RadioButton Content="M" IsChecked="{Binding Gender, Converter={StaticResource ResourceKey=genderConverterKey}, ConverterParameter=M}" />
<RadioButton Content="F" IsChecked="{Binding Gender, Converter={StaticResource ResourceKey=genderConverterKey}, ConverterParameter=F}" />

コンバーター

public class GenderConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((string)parameter == (string)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (bool)value ? parameter : null;        
    }
}

その場合にバインディングを適用しない場合は、nullConvertBack内)をBinding.DoNothingに置き換えます。

return (bool)value ? parameter : Binding.DoNothing;
14
user2880486

コマンドの使用(ここでは DelegateCommands を使用)

VM:

public enum Genders {
    Female,
    Male
}
public YourVMClass {
    public Genders SelectedGender {get; set;}

    private DelegateCommand _cmdSelectGender;

    public DelegateCommand CmdSelectGender {
        get { return _cmdSelectGender ?? (_cmdSelectGender = new DelegateCommand(SelectGender)); }
    }

    private void SelectGender(Object parameter) {
        SelectedGender = (Genders)parameter;
    }
}

XAML:

<Window.Resources>
    <ObjectDataProvider x:Key="listOfGenders" MethodName="GetValues"
                        ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="loca:Genders"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

<ItemsControl ItemsSource="{Binding Source={StaticResources listOfGenders}}">
    <ItemsControl.ItemTemplate>
        <RadioButton GroupName="Genders" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MainWindow}}, Path=DataContext.CmdSelectGender}" CommandParameter="{Binding}"/>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

(コードをテストしませんでしたが、これはアイデアです)

4
nkoniishvt

要件は可能ですが、それを機能させるために追加の作業が必要になります。この主な理由はRadioButtonのプロパティIsCheckedBooleanであり、複数のラジオボタンは個別のコントロールであり、1つのように機能しません。たとえば、ListBox。

要件が機能するためには、Converterを使用できます。両方のRadiobuttonsのIsCheckedをViewModelのPersonGenderプロパティにバインドし、共通のコンバーターを使用して、男性のラジオボタンに「MALE」、女性のラジオボタンに「FEMALE」のパラメーターを渡します。 。

ConverterでparameterPersonGenderが同じかどうかを確認し、その場合は[〜#〜] true [〜#〜]を返します。

つまり。チェックボックスコマンドパラメータがMALEで、PersonGenderもMALEの場合、チェックボックスが有効になります。チェックボックスコマンドパラメータがFEMALEで、PersonGenderがMALEの場合、falseであるため、チェックボックスは無効になります。戻ってきた。

1
ViVi

あなたがする必要があるのは IValueConverter を使用することで、BoolをCharに、またはその逆に変換します。例True => 'M';偽=> 'F'

ビューには2つのラジオボタンがあります。必ず同じグループ名で設定してください。次に、PersonGenderをIsMaleラジオボタンのみにバインドする必要があります。 Is女性ラジオボタンがチェックされているからです。同じグループ名のため、IsMaleラジオボタンは自動的にオフになります。

0
Tola Ch.