.net RelayCommands执行多次
我在WindowsPhone7(7.1使用WP8SDK和VSUltimate 2012)应用程序中使用MVVMLight,该应用程序从web服务应用程序异步检索数据。我在每个执行异步方法的页面上使用RelayCommands来获取数据,然后导航到下一个页面。例如,在我的一个ViewModels中,我声明了以下ICommand:.net RelayCommands执行多次,.net,windows-phone-7.1,mvvm-light,async-await,relaycommand,.net,Windows Phone 7.1,Mvvm Light,Async Await,Relaycommand,我在WindowsPhone7(7.1使用WP8SDK和VSUltimate 2012)应用程序中使用MVVMLight,该应用程序从web服务应用程序异步检索数据。我在每个执行异步方法的页面上使用RelayCommands来获取数据,然后导航到下一个页面。例如,在我的一个ViewModels中,我声明了以下ICommand: public ICommand ShowTreatmentDetailsCommand { get; set; } 然后,在VM的构造函数中,我按如下方式分配它: Sh
public ICommand ShowTreatmentDetailsCommand { get; set; }
然后,在VM的构造函数中,我按如下方式分配它:
ShowTreatmentDetailsCommand = new RelayCommand(ShowTreatmentDetails);
下面是该命令调用的方法:
private async void ShowTreatmentDetails()
{
try
{
Treatment refreshedTreatment = await treatmentService.LoadSingle(SelectedTreatment.id, LoggedUser.logon, LoggedUser.pwHash);
if (refreshedTreatment != null)
{
DrugGroup anaestGroup = null;
DrugGroup surgGroup = null;
IEnumerable<DrugGroup> groups = await drugGroupService.Load(
refreshedTreatment.id,
LoggedUser.logon,
LoggedUser.pwHash);
anaestGroup = groups
.Where(g => g.type == DrugType.Anaesthetic)
.SingleOrDefault<DrugGroup>();
surgGroup = groups
.Where(g => g.type == DrugType.Surgical)
.SingleOrDefault<DrugGroup>();
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add(Keys.AnaestDrugGroup, anaestGroup);
parameters.Add(Keys.SurgDrugGroup, surgGroup);
parameters.Add(Keys.SelectedTreatment, refreshedTreatment);
Messenger.Default.Send(parameters);
}
else
{
// Display error message
}
RefreshData();
}
catch (NullReferenceException) { }
}
private异步void showtreamentdetails()
{
尝试
{
治疗刷新治疗=等待治疗服务.LoadSingle(选择治疗.id,LoggedUser.logon,LoggedUser.pwHash);
if(刷新处理!=null)
{
药物组anaestGroup=null;
DrugGroup surgGroup=null;
IEnumerable groups=wait drugGroupService.Load(
refreshedTreatment.id,
LoggedUser.logon,
LoggedUser.pwHash);
麻醉组=组
.式中(g=>g.type==药物类型.麻醉剂)
.SingleOrDefault();
surgGroup=组
其中(g=>g.type==DrugType.Surgical)
.SingleOrDefault();
字典参数=新字典();
添加参数(key.AnaestDrugGroup,anaestGroup);
parameters.Add(key.SurgDrugGroup,surgGroup);
参数。添加(键。SelectedTreatment,refreshedTreatment);
Messenger.Default.Send(参数);
}
其他的
{
//显示错误消息
}
刷新数据();
}
捕获(NullReferenceException){}
}
当使用EventTrigger和EventToCommand类从列表框中选择项时,将从视图的xaml代码调用此命令(但与按钮相关的命令的问题仍然存在。以防万一,下面是我的列表框元素:
<ListBox x:Name="lbxTreatmentList"
ItemsSource="{Binding Treatments}"
SelectedItem="{Binding SelectedTreatment, Mode=TwoWay}">
<int:Interaction.Triggers>
<int:EventTrigger EventName="SelectionChanged">
<com:EventToCommand Command="{Binding ShowTreatmentDetailsCommand}"
PassEventArgsToCommand="True" />
</int:EventTrigger>
</int:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<custom:TreatmentListItem PatientName="{Binding patient}"
OpeDescription="{Binding description}"
StartedAt="{Binding startedAt}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
还有一个按钮的例子:
<Button Grid.Row="2"
HorizontalAlignment="Center"
Foreground="{StaticResource BeldicoBlue}"
BorderBrush="{StaticResource BeldicoBlue}"
Margin="0,12,0,0"
Padding="24,12"
Command="{Binding ValidateCommand}">
<TextBlock Text="Validate this treatment" FontWeight="ExtraBold" />
</Button>
问题是,每次启动命令时,相关方法的执行次数都在增加。即:第一次调用时执行一次,然后执行两次,然后执行三次、四次、五次…次。由于方法中存在异步服务调用,因此这很快会占用带宽和时间
我绝对不明白这种行为背后的原因,有人能帮忙吗?这里有两种可能的情况:
SelectionChanged
事件的工作方式。当选择更改时,此事件可能会触发多次。如果已经有选定的项目,则在删除该项目时将触发更改的事件,然后在添加新的选定项目时再次触发。如果您直接使用事件处理程序,则可以直接查询
SelectionChangedEventArgs
,以确定触发事件的原因。但是,您的代码忽略了这些参数,即使xaml表示您正在传递它们
e、 g
为什么要定义
公共ICommand ShowTreatmentDetailsCommand
,然后定义ShowTreatmentDetailsCommand=new RelayCommand
。用RelayCommand替换ICommand。可能不会解决您的问题,但如果我做对了,我不会。单击按钮,方法将被调用一次。再次单击按钮,方法将被禁用调用了两次,对吗?您是否查看了每次执行的堆栈跟踪,以找出触发执行的原因?@Rudi:我将我的命令声明为ICommand,因为ICommand是在.NET framework中构建的,而RelayCommand继承了ICommand接口,但随MVVM Light包而来。将命令声明为RelayCommands代替ICommand没有什么区别,但我只是习惯性地使用ICommand。是的,你的问题是对的。我也考虑过NR1,因为这也发生在我身上,但根据他的代码,我(我们)看不到他在何处或何时调用/创建ViewModel。SelectionChangedEvent考虑得很好,但他说当他单击按钮时也会发生这种情况,所以我认为这更可能是第1个问题。这实际上是我的第2个解决方案。我不知道SelectionChanged事件在每次选择时都会触发多次,谢谢分享提示。顺便说一下,在我的情况下,检查args.AddedItems.Count是否严格等于1,而不是“小于或等于”效果更好。我以前在一些按钮上也有类似的错误,但当我重构我的视图层时,它似乎已经被修复,使它在每次导航时都系统地调用CleanViewModel方法。IMHOSelectionChangedEventArgs
在Viewmodel
中会使该方法与视图耦合,因此它在没有moc的情况下无法测试king theselection changedeventsargs
还有更优雅的方式吗?
ShowTreatmentDetailsCommand =
new RelayCommand<SelectionChangedEventArgs>(ShowTreatmentDetails);
private async void ShowTreatmentDetails(SelectionChangedEventArgs args)
{
if (args.AddedItems.Count >= 1)
{
// your code
}
}