我有两个单选按钮,它们使用双向绑定到视图模型的两个布尔属性X
和Y
。由于单选按钮是互斥的,因此设置X
会自动清除Y
,反之亦然。现在,如果我导航到另一个页面,请返回,再次导航到该页面,然后使用单选按钮返回该页面,按钮将停止工作。
重现该问题的步骤:
在App.xaml.cs中,在第sealed partial class App : Application
行之前添加以下代码(请包含System.ComponentModel
和System.Runtime.CompilerServices
名称空间)
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();
在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));
}
}
在项目中添加空白页,并在其.xaml文件中将其页面内容替换为
<Grid>
<Button Click="Button_Click" Content="Back"/>
</Grid>
并在其.cs文件中,添加以下按钮处理程序
private void Button_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(MainPage));
}
编译并启动该应用程序,一旦运行,请单击单选按钮以确认它们正在运行。
单击导航,然后单击上一步。单选按钮此时正在工作。
再次单击“导航”,然后单击“上一步”。这些按钮不再起作用。
是什么原因导致按钮停止工作?这是错误还是我错过了某些东西,并且行为正常?谢谢。
答案 0 :(得分: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>
有帮助吗?
答案 1 :(得分:0)
首先,最好在UI完全加载之前初始化Core ViewModel,这会使绑定更平滑。
为此,请在XAML上创建Datacontext对象。
<MainPage.DataContext> <yourviewmodelnamespace:YourViewModel/> </MainPage.DataContext> <Grid> etc....
要引用您的dataconext,请在Page类之内创建“仅获取”属性,例如
public YourViewModel mydatacontext{ get{ return DataContext as YourViewModel;} }
说了这么多,就简化了。
您只需要一个“属性绑定”,并且由于只有两个选项,因此应该在彼此上方使用两个复选框,第一个复选框将绑定到属性的常规值,而另一个复选框则相反
请注意,复选框 IsChecked 实际上是可为空的布尔值(布尔值)。如前所述,为了实现这一单一财产制度,您将必须使用称为 Converter 的东西,在我们的例子中,这将简单地反转输入值,这一切似乎都很复杂,但我向您保证实现此类功能的最简洁,最有效的方法。
示例代码: 1. YourViewModel.cs
private bool? _y; public bool? IsYCheckboxChecked { get => _y; set { if (value != _y) { _Y = value; OnPropertyChanged(); } } }
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; } } }
<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>
所有内容都是从头顶和脚底写出来的,因此请原谅格式,编辑器太迟钝和笨拙,即使绑定表达式看起来像是多行,也不要将其分解成不同的行。
Edit:build最好在每个步骤之后构建项目,因为xaml编辑器通常不会立即识别诸如普通类或转换器之类的非ui frameork元素。