0

ビューモデルの列挙プロパティを、ビューのラジオボタンのセットとして表現しようとしています。ここまでは順調ですね; 私はそれを双方向で表現することができますMultiBinding

(rb1.IsChecked、rb2.IsChecked、rb3.IsChecked)<-> vm.Value

ここで使用されるマルチバインディングは、(bool, bool, bool) <-> MyValue;間で変換するマルチコンバーターを備えています。明らかに、タイプの(3つの)許容値の1つは、に基づいMyValueて選択され、その逆も同様です。booltrue

ただし、これはすでに少し不便です。マルチバインディングは単一の値の側から定義する必要があるため、ビューのXamlでそのバインディングを定義することはできません。したがって、コードビハインドでマルチバインディングを定義SetBindingし、ビューモデルのValueプロパティでsetを使用する必要があります。

さて、私が立ち往生している問題は、ラジオボタンの1つのセットをその値にバインドするだけでなく、2つをバインドしていることです。したがって、私のバインディングは次のようになります。

(rbA1.IsChecked、rbA2.IsChecked、rbA3.IsChecked)<-> vm.Value <->(rbB1.IsChecked、rbB2.IsChecked、rbB3.IsChecked)

SetBinding問題は、一度に複数のバインディングを接続するために使用できないことvm.Valueです。

私がこれまでに試した解決策は次のとおりです。

  • 1つの大きなマルチバインディングを使用して、一度にすべてのラジオボタンにバインドします。これは、フォームのバインドを意味し(rbA1.IsChecked, rbA2.IsChecked, rbA3.IsChecked, rbB1.IsChecked, rbB2.IsChecked, rbB3.IsChecked) <-> vm.Valueます。このソリューションの問題は、ラジオボタンの1つ(たとえば)がチェックされている場合、 (チェックされていない)または(チェックされている)が「新しい正しい」値rbB2を持っているかどうかを判断する方法がないことです。rbA2rbB2
  • 最初に、 1つのプロパティのみを公開するラジオグループコントロールを定義して、ラジオボタングループを抽象化しSelectedIndexます。このプロパティは、ラジオグループコントロールvm.Valueのすべてのインスタンスからプロパティに便利にバインドできます。実行可能ですが、新しい制御クラスを作成する必要があり、これがWPFでの唯一の方法であるかどうか疑問に思います。
  • あるラジオボタンのセットを別のラジオボタンにバインドする:、、などに双方向でバインドrbB1rbA1、ラジオボタンの最初のセットとの間でのみマルチバインドを使用するとrbB2、目的の効果が得られますが、 「マスターラジオグループ」を持つという概念は好きではありません。データ転送のためにGUI要素を悪用することになります。rbA2vm.Value
  • コードビハインドですべてを実行し、ラジオボタンとビューモデル値を手動で更新します。もちろん、これは実行可能なフォールバックソリューションですが、これはXaml /バインディングを使用して実行可能であると思われます。
4

2 に答える 2

0

コンバーターと分離コードで複雑なマルチバインディングを使用すると、コードのデバッグが難しくなるだけでなく、テストもさらに難しくなります。私の意見では、ラジオボタン(フラグ)の各セットをビューモデルとして表現する方がよいと思います。ラジオボタンのいずれかがオン/オフになっているときに値を評価します。

RadioButtonGroup

public class RadioButtonGroup : ViewModel {

    public RadioButtonGroup(string groupName, int count, Action<bool[]> whenAnyChanaged = null) {

        RadioButtons = Enumerable.Range(0, count).Select(_ => {
            var button = new RadioButton { GroupName = groupName };
            button.PropertyChanged += (s, e) => {
                if (e.PropertyName == "IsChecked")
                    whenAnyChanaged(Flags);
            };
            return button;
        }).ToList();           
    }

    public List<RadioButton> RadioButtons { get; private set; }

    public bool[] Flags { get { return RadioButtons.Select(rb => rb.IsChecked).ToArray(); } }
}

ラジオボタン

 public class RadioButton : ViewModel {

    private bool isChecked;

    public bool IsChecked {
        get { return isChecked; }
        set { SetProperty(ref this.isChecked, value); }
    }

    public string GroupName { get; set; }
}

MainViewModel

public class MainViewModel : ViewModel {
    public MainViewModel() {
        GroupA = new RadioButtonGroup("A", 10, flags => GroupToggle(flags, GroupB.Flags));
        GroupB = new RadioButtonGroup("B", 10, flags => GroupToggle(GroupA.Flags, flags));
    }

    public RadioButtonGroup GroupA { get; private set; }

    public RadioButtonGroup GroupB { get; private set; }

    void GroupToggle(bool[] groupA, bool[] groupB) {
        MyValue = Evaluate(groupA, groupB);
    }
}

意見

<Window x:Class="WpfLab.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="{Binding Title}" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="RadioButton">
        <RadioButton IsChecked="{Binding IsChecked, Mode=OneWayToSource}" GroupName="{Binding GroupName}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="30"/>
        <RowDefinition Height="30"/>
    </Grid.RowDefinitions>

    <ListBox Grid.Row="0" ItemsSource="{Binding GroupA.RadioButtons}" ItemTemplate="{StaticResource ResourceKey=RadioButton}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

    <ListBox Grid.Row="1" ItemsSource="{Binding GroupB.RadioButtons}" ItemTemplate="{StaticResource ResourceKey=RadioButton}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</Grid>

于 2012-09-22T10:42:17.750 に答える
0

VMEnumを各RadioButtonに個別にバインドします(単一の双方向バインディングを使用します)。各バインディングには、列挙型のCommandParameterが必要です。好き:

<RadioButton IsChecked="{Binding VMEnum, Converter={StaticResource EnumConverter}, ConverterParameter={Enums:VMEnums.FirstRadioButtonGroupA}}" />

コンバーターでは、

  • Convertは、VMEnumとCOmmandParameterに応じて、正しい値(true / false)を返す必要があります。基本的に、ロジックはVMEnum ==(YourEnum)CommandParameterです。
  • ConvertBackは、IsCheckedに基づいて正しい列挙型を返す必要があります。IsCheckedがtrueの場合、正しい列挙型を返します。それ以外の場合は、Binding.DoNothingを返します。これにより、その特定のケースのバインディングが中止されます。
于 2012-09-22T18:34:39.983 に答える