首页 > 解决方案 > WPF 和棱镜:单选按钮选择在多个用户控件上消失

问题描述

InteractionRequestTrigger在几个用户控件中使用 Prism 来使用我自己的窗口内容显示通知,例如TestControl包含三个RadioButtons. 在 VM 创建时间中,TestControl我在第一个单选按钮上设置了选择。

问题是,当显示最后一个窗口时,单选按钮被选中。但是之前创建的所有其他窗口都没有任何选择。I figured out that my EnumToBooleanConverter's ConvertBackfunction is called and unselects again it when the first radio button of the next user control was selected. 等等……你知道为什么吗?如何解决这个问题?

这是重现此问题的简单代码:

主窗口:

  <Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:prism="http://www.codeplex.com/prism"
    xmlns:local="clr-namespace:WpfApp1"
    xmlns:vm="clr-namespace:WpfApp1.ViewModels" Title="MainWindow">
<StackPanel>
    <i:Interaction.Triggers>
        <prism:InteractionRequestTrigger SourceObject="{Binding StretchModeRequest1}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <local:TestControl/>
                </prism:PopupWindowAction.WindowContent>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>

        <prism:InteractionRequestTrigger SourceObject="{Binding StretchModeRequest2}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <local:TestControl/>
                </prism:PopupWindowAction.WindowContent>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>

        <prism:InteractionRequestTrigger SourceObject="{Binding StretchModeRequest3}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <local:TestControl/>
                </prism:PopupWindowAction.WindowContent>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers>

    <Button Content="Command 1" Margin="5" Command="{Binding ClickCommand}" CommandParameter="1"/>
    <Button Content="Command 2" Margin="5" Command="{Binding ClickCommand}" CommandParameter="2"/>
    <Button Content="Command 3" Margin="5" Command="{Binding ClickCommand}" CommandParameter="3"/>

</StackPanel>

主视图模型:

public class ViewModel : BindableBase
{
    public InteractionRequest<Confirmation> StretchModeRequest1 { get; private set; }
    public InteractionRequest<Confirmation> StretchModeRequest2 { get; private set; }
    public InteractionRequest<Confirmation> StretchModeRequest3 { get; private set; }

    public ICommand ClickCommand { get; private set; }

    public ViewModel()
    {
        StretchModeRequest1 = new InteractionRequest<Confirmation>();
        StretchModeRequest2 = new InteractionRequest<Confirmation>();
        StretchModeRequest3 = new InteractionRequest<Confirmation>();

        ClickCommand = new DelegateCommand<object>(OnClicked);
    }

    private void OnClicked(object obj)
    {
        int index = Convert.ToInt32(obj);
        var confirmation = new Confirmation() { Content = "Test", Title = string.Format("Bla {0}", index) };
        switch (index)
        {
            case 1: StretchModeRequest1.Raise(confirmation); break;
            case 2: StretchModeRequest2.Raise(confirmation); break;
            case 3: StretchModeRequest3.Raise(confirmation); break;
            default:
                break;
        }
    }
}

测控:

 <UserControl x:Class="WpfApp1.TestControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApp1"
         xmlns:vm="clr-namespace:WpfApp1.ViewModels">
<UserControl.Resources>
    <ResourceDictionary>
        <local:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>
    </ResourceDictionary>
</UserControl.Resources>

<UserControl.DataContext>
    <vm:TestViewModel/>
</UserControl.DataContext>

<StackPanel Margin="3,3,3,0">

    <RadioButton Margin="2" GroupName="Mode" Content="None" IsChecked="{Binding SelectedMode, 
        diag:PresentationTraceSources.TraceLevel=High, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.None}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <RadioButton Margin="2" GroupName="Mode" Content="Limits" IsChecked="{Binding SelectedMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.Limits}, Mode=TwoWay}"/>
    <RadioButton Margin="2" GroupName="Mode" Content="Static" IsChecked="{Binding SelectedMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.Static}, Mode=TwoWay}"/>
</StackPanel>

测试视图模型:

public class TestViewModel : BindableBase
{
    private StretchType _stretchMode;

    public TestViewModel()
    {
        SelectedMode = StretchType.None;
    }

    public StretchType SelectedMode
    {
        get { return _stretchMode; }
        set { SetProperty(ref _stretchMode, value); }
    }
}

转换器:

public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.Equals(parameter);
    }

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

标签: c#wpfxamlprism

解决方案


GroupName您应该为每个视图使用唯一的,例如:

<RadioButton Margin="2" GroupName="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" Content="None" IsChecked="{Binding SelectedMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.None}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<RadioButton Margin="2" GroupName="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" Content="Limits" IsChecked="{Binding SelectedMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.Limits}, Mode=TwoWay}"/>
<RadioButton Margin="2" GroupName="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" Content="Static" IsChecked="{Binding SelectedMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static vm:StretchType.Static}, Mode=TwoWay}"/>

推荐阅读