1

同時に開かれる 2 つのウィンドウで次のコントロール テンプレートを使用しており、両方とも同じビューモデルを使用しています。テンプレートは次のとおりです。

    <ControlTemplate x:Key="SecurityTypeSelectionTemplate">
        <StackPanel>
            <RadioButton GroupName ="SecurityType"  Content="Equity" 
                     IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumBoolConverter}, ConverterParameter=Equity}" />
            <RadioButton GroupName ="SecurityType" Content="Fixed Income" 
                     IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumBoolConverter}, ConverterParameter=FixedIncome}" />
            <RadioButton GroupName ="SecurityType" Content="Futures" 
                     IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumBoolConverter}, ConverterParameter=Futures}" />
        </StackPanel>
    </ControlTemplate>

ビューモデルのプロパティは次のとおりです。

    private SecurityTypeEnum _securityType;
    public SecurityTypeEnum SecurityType
    {
        get { return _securityType; }
        set
        {
            _securityType = value; RaisePropertyChanged("SecurityType");
        }
    }

列挙型は次のとおりです。

public enum SecurityType { Equity, FixedIncome, Futures }

コンバーターは次のとおりです。

public class EnumToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object enumTarget, CultureInfo culture)
    {
        string enumTargetStr = enumTarget as string;
        if (string.IsNullOrEmpty(enumTargetStr))
            return DependencyProperty.UnsetValue;

        if (Enum.IsDefined(value.GetType(), value) == false)
            return DependencyProperty.UnsetValue;

        object expectedEnum = Enum.Parse(value.GetType(), enumTargetStr);

        return expectedEnum.Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object enumTarget, CultureInfo culture)
    {
        string expectedEnumStr = enumTarget as string;
        if (expectedEnumStr == null)
            return DependencyProperty.UnsetValue;

        return Enum.Parse(targetType, expectedEnumStr);
    }
}

問題は少し奇妙です。同じ ViewModel のわずかに異なるビューを表示している 2 つのウィンドウがあります。上記の同じテンプレートが両方のビューで再利用されます。Equity が最初に SecurityType として設定されている場合、関連するラジオ ボタンをクリックして、これを FixedIncome に変更できます。その後、Equity に戻すことはできません。ただし、先物に設定することはできます。しかし、その後、関連するラジオ ボタンをクリックして FixedIncome または Equity に変更することはできません。
変更を元に戻すことができない場合に何が起こっているかは、Setter が 2 回呼び出されることです。初めて値を正しい選択値に設定しますが、RaisePropertyChanged が起動された瞬間に、今度は元の値でセッターが再度呼び出されます。
RaisePropertyChanged の場合、2 番目のウィンドウからバインディングによってセッターが呼び出され、ユーザーが選択した最初のウィンドウに設定されている値が上書きされるように感じます。これが事実であるかどうか、またこのシナリオで回避する方法を知っている人はいますか?

4

2 に答える 2

1

EnumToBoolConverter の私のバージョンは次のとおりです。

public class EnumToBoolConverter : BaseConverterMarkupExtension<object, bool>
    {
        public override bool Convert(object value, Type targetType, object parameter)
        {
            if (value == null)
                return false;

            return value.Equals(Enum.Parse(value.GetType(), (string)parameter, true));
        }

        public override object ConvertBack(bool value, Type targetType, object parameter)
        {
            return value.Equals(false) ? DependencyProperty.UnsetValue : parameter;
        }
    }
于 2013-02-26T20:51:20.613 に答える
1

RadioButton の既定の動作では、プロパティが変更されたときにソースが更新されるため、両方のウィンドウがソースを更新しようとします。1 つの修正方法は、ユーザーがクリックした場所からのみソースを更新することです。これを行うには、バインディングでBinding.UpdateSourceTrigger Explict を使用します。RadioButton のコード ビハインドにクリック ハンドラを追加します。その中で明示的にソースを更新します。

        <StackPanel>
        <RadioButton GroupName ="SecurityType"  Content="Equity" 
                 IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, UpdateSourceTrigger=Explicit, ConverterParameter=Equity}" Click="RadioButton_Click" />
        <RadioButton GroupName ="SecurityType" Content="Fixed Income" 
                 IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, UpdateSourceTrigger=Explicit, ConverterParameter=FixedIncome}" Click="RadioButton_Click"/>
        <RadioButton GroupName ="SecurityType" Content="Futures" 
                 IsChecked="{Binding Path=SecurityType, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, UpdateSourceTrigger=Explicit, ConverterParameter=Futures}" Click="RadioButton_Click"/>
    </StackPanel>  

    private void RadioButton_Click(object sender, RoutedEventArgs e)
    {
        BindingExpression be = ((RadioButton)sender).GetBindingExpression(RadioButton.IsCheckedProperty);
        be.UpdateSource();
    }

ビューで分離コードを取得するには、ControlTemplate の代わりに、または ControlTemplate 内で UserControl を使用する必要がある場合があります。

于 2013-02-26T22:05:54.873 に答える