Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当使用相同的ViewModel打开两个窗口时,无法设置单选按钮值_C#_.net_Wpf_Mvvm - Fatal编程技术网

C# 当使用相同的ViewModel打开两个窗口时,无法设置单选按钮值

C# 当使用相同的ViewModel打开两个窗口时,无法设置单选按钮值,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我在两个同时打开的窗口中使用以下控件模板,并且两个窗口都使用相同的viewmodel。 这是模板 <ControlTemplate x:Key="SecurityTypeSelectionTemplate"> <StackPanel> <RadioButton GroupName ="SecurityType" Content="Equity" IsChecked="{Bi

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

    <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>
以下是枚举:

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的略有不同的视图。上述相同的模板在两个视图中重复使用。 如果Equity最初设置为SecurityType,我可以通过单击相关单选按钮将其更改为FixedIncome。我不能把它改回衡平法。 不过,我可以把它设定为未来。但之后,我无法通过单击相关单选按钮将其更改为FixedIncome或Equity。
在我无法将其设置回更改的情况下发生的情况是,设置器被调用了两次。第一次将该值设置为正确的选定值,但触发RaisePropertyChanged时, 再次调用setter,这次使用原始值。
这感觉就像当RaisePropertyChanged时,setter被第二个窗口的绑定调用,从而覆盖了在用户进行选择的第一个窗口中设置的值。
是否有人知道这种情况以及在这种情况下如何避免?

以下是我的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;
        }
    }
公共类EnumToBoolConverter:BaseConverterMarkupExtension
{
公共覆盖布尔转换(对象值、类型targetType、对象参数)
{
如果(值==null)
返回false;
返回value.Equals(Enum.Parse(value.GetType(),(string)参数,true));
}
公共重写对象转换回(布尔值、类型targetType、对象参数)
{
返回值.Equals(false)?DependencyProperty.Unset值:参数;
}
}

单选按钮的默认行为是在属性更改时更新源,以便两个窗口都尝试更新源。一种修复方法是仅从用户单击的位置更新源。要做到这一点,请在装订上明确说明。在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();
    }

专用void单选按钮单击(对象发送者,路由目标e)
{
BindingExpression be=((RadioButton)发送方).GetBindingExpression(RadioButton.IsCheckedProperty);
be.UpdateSource();
}

您可能必须使用UserControl而不是ControlTemplate,或者在ControlTemplate中使用UserControl才能在视图中隐藏代码。

您的EnumBoolConverter是什么样子的?我曾经遇到过同样的问题,发现是我的转换器把一切都搞糟了,但我记不清到底是什么问题。我编辑了这篇文章,把转换器也包括进去。迈克:看看我的答案。
enumtoolconverter
应在
ConvertBack
中返回布尔值。试试看,让我知道。是的,这解决了问题。在这种情况下,Convert和ConvertBack都返回布尔值?当你想到“转换回”这个词时,这有点不直观……但现在我不得不去想它,我想这是有道理的。多谢!不,我错了。实际上ConvertBack返回
参数
值(实际上是一个字符串,仅当尝试“转换回”时)
RadioButton.IsChecked=true
到Enum。我想绑定框架本身能够将字符串转换为Enum值。谢谢。我最初尝试过这个,但我确实希望在新选择选项时更新另一个窗口,因此此解决方案不适合我。对于这种情况,EnumToBoolConverter是答案b因为这是最简单的。但UpdateSourceTrigger可能会帮助其他人。主要的一点是UpdateSourceTrigger让您可以控制何时更新绑定源。如本文所示,当用户通过RadioButton\u Click事件在一个窗口中选择新选择的选项时,它会特别更新其他窗口。
        <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();
    }