1

我有两个单选按钮,它们使用双向绑定到两个布尔属性XY我的视图模型。由于单选按钮是互斥的,设置会X自动清除Y,反之亦然。现在,如果我导航到另一个页面,然后返回,再次导航到该页面并返回带有单选按钮的页面,这些按钮将停止工作。

重现问题的步骤:

  1. 创建一个新的 C# 通用 Windows 空白应用程序。
  2. 将最低版本和目标版本设置为 1809(1803 和 Fall Creators Update 的问题仍然存在)
  3. 在 App.xaml.cs 中,在行前添加以下代码sealed partial class App : Application(Do include System.ComponentModeland System.Runtime.CompilerServicesnamespaces)

    public class ViewModel : INotifyPropertyChanged
    {
        private bool _X;
        public bool X
        {
            get => _X;
            set
            {
                if (value != _X)
                {
                    _X = value;
                    OnPropertyChanged();
                }
            }
        }
    
        private bool _Y;
        public bool Y
        {
            get => _Y;
            set
            {
                if (value != _Y)
                {
                    _Y = value;
                    OnPropertyChanged();
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    

    并在课堂App上添加

    public static ViewModel VM = new ViewModel();
    
  4. 在 MainPage.xaml 中,将页面内容替换为

    <StackPanel>
        <RadioButton IsChecked="{x:Bind VM.X, Mode=TwoWay}" Content="X"/>
        <RadioButton IsChecked="{x:Bind VM.Y, Mode=TwoWay}" Content="Y"/>
        <Button Content="Navigate" Click="Button_Click"/>
    </StackPanel>
    

    并在 MainPage.xaml.cs 中,将MainPage类替换为

    public sealed partial class MainPage : Page
    {
        public ViewModel VM => App.VM;
    
        public MainPage()
        {
            InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(BlankPage1));
        }
    }
    
  5. 向您的项目添加一个空白页面,并在其 .xaml 文件中,将其页面内容替换为

    <Grid>
        <Button Click="Button_Click" Content="Back"/>
    </Grid>
    

    并在其 .cs 文件中,添加以下按钮处理程序

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Frame.Navigate(typeof(MainPage));
    }
    
  6. 编译并启动应用程序,一旦它运行,单击单选按钮以确认它们正在工作。

  7. 单击导航,然后单击返回。此时单选按钮正在工作。

  8. 再次单击导航,然后单击返回。按钮不再起作用。

是什么导致按钮停止工作?这是一个错误还是我错过了一些东西并且行为是预期的?谢谢。

4

2 回答 2

2

尝试将组名添加到您的单选按钮:

<StackPanel>
    <RadioButton IsChecked="{x:Bind VM.X, Mode=TwoWay}" Content="X" GroupName="Group1"/>
    <RadioButton IsChecked="{x:Bind VM.Y, Mode=TwoWay}" Content="Y" GroupName="Group1"/>
    <Button Content="Navigate" Click="Button_Click"/>
</StackPanel>

它有帮助吗?

于 2019-01-12T08:38:29.737 回答
0

首先,最好在 ui 完全加载之前初始化您的 Core ViewModel,它只会使绑定更顺畅。

为此,请在 XAML 上创建 Datacontext 对象。在 - 的里面

 <MainPage.DataContext>
<yourviewmodelnamespace:YourViewModel/>
</MainPage.DataContext> 
<Grid> 
etc....

参考你的dataconext在Page类中创建一个Get only属性,比如

public YourViewModel mydatacontext{
get{
return DataContext as YourViewModel;}
}

说了这么多,让我们简化一下。

您只需要一个属性绑定,并且由于您只有两个选项,因此您应该使用两个相互叠加的复选框,第一个复选框将绑定到属性的正常值,另一个复选框将相反。

请注意 Checkboxes IsChecked实际上是一个可为空的布尔值(布尔值?)。如前所述,为了实现这一属性系统,您将不得不使用所谓的 A转换器,在我们的例子中,它将简单地反转传入的值,这一切可能看起来很复杂,但我向您保证它是最干净和最有效的实现方式这样的功能。

示例代码: 1. YourViewModel.cs

  private bool? _y;
    public bool? IsYCheckboxChecked
    {
        get => _y;
        set
        {
            if (value != _y)
            {
                _Y = value;
                OnPropertyChanged();
            }
        }
    }
  1. 转换器类
namespace YourConvertNameSpace{

public Class NullBoolReverser{// this is the converter we are going to use to reverse the bool?
 public object Convert(object value, Type targetType, object parameter, string language)
            {
                var val = (bool?)value;

                return !val;
            }

            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                var val = (bool?)value;

                return !val;
            }
}


}
  1. 主页.xaml
<MainPage.Resources>
    <YourConvertNameSpace:NullBoolReverser x:Key="MyReverserKey"/>
</MainPage.Resources>

<MainPage.DataContext>
    <your datacontextgoes here, like i showed before, it will be accessed by a get only prop called 'mydatacontext'>
    </MainPage.DataContext>

    <Grid>
        <StackPanel
            <CheckBox Name="Ycheckbox"  IsChecked="{x:Bind 'mydatacontext.IsYCheckboxChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                      This is Y
            </CheckBox

            <CheckBox IsChecked="{x:Bind Ycheckbox.IsChecked, Converter={StaticResource MyReverserKey}, Mode=TwoWay}">
                      This is X
            </CheckBox><!--This Bind Allows a and exclusive clause between the two cheboxes thanks to the nullbool reverser-->

        </StackPanel
    </Grid
</Page>

这都是从头顶和脚上写出来的,所以请原谅格式,编辑器太乏味和笨重,不要将绑定表达式分成不同的行,即使它们看起来是多行的。

编辑:构建 在每一步之后构建您的项目是很好的,因为 xaml 编辑器通常不会立即识别普通类或转换器等非 ui 框架元素。

于 2019-01-12T15:41:06.560 回答