1

我在同时打开的两个窗口中使用以下控件模板,并且都使用相同的视图模型。这是模板;

    <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);
    }
}

问题有点奇怪。我有两个窗口显示 SAME ViewModel 的视图略有不同。上面显示的相同模板在两个视图中重复使用。如果 Equity 最初设置为 SecurityType,我可以通过单击相关单选按钮将其更改为 FixedIncome。然后我无法将其更改回股权。但是,我可以将其设置为期货。但在那之后,我无法通过单击相关单选按钮将其更改为 FixedIncome 或 Equity。
在我无法设置更改的情况下发生的情况是 Setter 被调用了两次。第一次将值设置为正确的选定值,但在触发 RaisePropertyChanged 的​​那一刻,再次调用设置器,这次使用原始值。
感觉就像当 RaisePropertyChanged 时,setter 被第二个窗口的绑定调用,从而覆盖了用户进行选择的第一个窗口中设置的值。有谁知道这是否是这种情况以及在这种情况下如何避免?

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 的默认行为是在属性更改时更新源,因此两个窗口都尝试更新源。一种解决方法是仅从用户单击的位置更新源。为此,请在绑定上使用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();
    }

您可能必须使用 UserControl 代替 ControlTemplate 或在 ControlTemplate 中使用您的视图中的代码。

于 2013-02-26T22:05:54.873 回答