RelayCommands被执行多次

ZipionLive

我在Windows Phone 7(使用wp8 SDK和VS Ultimate 2012的7.1)应用程序中使用MVVM Light,该应用程序从Web服务应用程序中异步检索数据。我在每个页面上使用RelayCommands,它们执行异步方法来获取数据,然后导航到下一页。例如,在我的一个ViewModels中,我声明了以下ICommand:

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) { }
}

当使用EventTrigger和EventToCommand类从ListBox中选择一个项目时,会从View的xaml代码中调用此命令(但是问题仍然存在于与按钮相关的命令中。以防万一,这是我的ListBox元素:

<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>

问题在于,每次触发命令时,相关方法的执行次数都会增加。即:第一次拨打一次,然后两次,然后三,四,五...次。由于该方法中存在异步服务调用,因此这很快变得带宽和耗时。

我绝对不了解这种行为背后的原因,有人可以帮忙吗?

马特·莱西

这里发生了一些可能的事情:

  1. 您正在创建附加到页面的多个viewmodel实例,每个实例都在执行命令。

    或者,更有可能:

  2. 您没有完全了解SelectionChanged事件的工作方式。选择更改时,可以多次触发此事件。如果已经有一个选定的项目,则该事件将在删除该项目时触发,然后在添加新的选定项目时再次触发。
    如果您直接使用事件处理程序,则可以SelectionChangedEventArgs直接查询,以确定触发事件的原因。即使您的xaml说您正在传递它们,您的代码仍会忽略这些args。

如果您更改操作以使其支持这些参数,则可以在此处添加检查。
例如

ShowTreatmentDetailsCommand =
     new RelayCommand<SelectionChangedEventArgs>(ShowTreatmentDetails);

private async void ShowTreatmentDetails(SelectionChangedEventArgs args)
{
    if (args.AddedItems.Count >= 1)
    {
        // your code
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章