我正在使用Caliburn.Micro - 并希望添加一个可检查的menuitem。此操作的处理程序需要知道菜单项的状态 - 是否已选中。
XAML:
<MenuItem Header="Laser" x:Name="ToggleLaser" VerticalAlignment="Top" IsCheckable="True" IsChecked="{Binding LaserState}" >
ViewModel(不包括错误恢复代码):
public IEnumerable<IResult> ToggleLaser(bool isChecked)
{
yield return BusyResult.Show("Turning laser " + (isChecked ? "on" : "off");
if (isChecked)
yield return TurnOnLaserAsync().AsResult();
else
yield return TurnOffLaserAsync().AsResult();
LaserState = isChecked;
yield return BusyResult.Hide();
}
这不起作用 - isChecked总是错误的。
我可以获取eventargs:
public IEnumerable<IResult> ToggleLaser(RoutedEventArgs eventArgs)
{
var menuItem = (MenuItem)eventArgs.OriginalSource;
var isChecked = menuItem.IsChecked;
return ToggleLaser(isChecked);
}
然后我的viewmodel绑定到我的视图 - 不太好。
我在这里找不到一个好的答案,所以将其发布在那里,因为我确信这是一个非常正常的菜单项用例。
答案 0 :(得分:0)
我提出的一个解决方案是通过添加新的数据绑定关键字来扩展caliburn框架:
MessageBinder.SpecialValues.Add("$ischecked", context =>
{
var args = context.EventArgs as RoutedEventArgs;
if (args == null) {
return null;
}
var fe = args.OriginalSource as MenuItem;
if (fe == null) {
return null;
}
return fe.IsChecked;
});
然后我的XAML变成:
<MenuItem Header="Laser" x:Name="ToggleLaser" VerticalAlignment="Top" IsCheckable="True" cal:Message.Attach="ToggleLaser($ischecked)"/>
我的viewmodel变为
public void ToggleLaser(bool turnOn)
{
if (turnOn)
TurnOnLaser();
else
TurnOffLaser();
}
好多了。 : - )
我想第二种方法是对menuitem IsChecked属性进行数据绑定 - 这有利于处理启动激光器出错的情况 - 但我不喜欢在属性设置器中调用复杂函数,所以我认为更好的解决方案是数据绑定IsChecked 和使用特定的处理程序。
非常感谢。
答案 1 :(得分:0)
您可以执行以下操作:
<MenuItem Header="Laser"
x:Name="ToggleLaser"
VerticalAlignment="Top"
IsCheckable="True"
IsChecked="{Binding IsLaserOn}">
和ViewModel:
public bool IsLaserOn
{
get { return this.isLaserOn; }
set
{
if (value == this.isLaserOn)
return;
this.isLaserOn = value;
this.RaisePropertyChanged("IsLaserOn");
this.ToggleLaser(this.isLaserOn);
}
}
它更简单,而不是创建一些MessageBinder。