2

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

问题是,每次触发命令时,相关方法的执行次数都会增加。即:第一次通话时一次,然后两次,然后是三、四、五……次。由于该方法中有一个异步服务调用,因此很快就会变得带宽和耗时。

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

4

1 回答 1

1

这里有几件可能发生的事情:

  1. 您正在创建附加到页面的多个视图模型实例,并且每个实例都在执行命令。

    或者,更有可能:

  2. 您没有完全考虑SelectionChanged事件的运作方式。This event can be triggered multiple times when the selection changes. 如果已经有一个选定的项目,则在删除该项目时将触发 changed 事件,然后在添加新的选定项目时再次触发。
    如果您直接使用事件处理程序,则可以直接查询SelectionChangedEventArgs以确定触发事件的原因。您的代码忽略了这些参数,即使您的 xaml 说您正在传递它们。

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

ShowTreatmentDetailsCommand =
     new RelayCommand<SelectionChangedEventArgs>(ShowTreatmentDetails);

private async void ShowTreatmentDetails(SelectionChangedEventArgs args)
{
    if (args.AddedItems.Count >= 1)
    {
        // your code
    }
}
于 2013-07-10T09:36:49.530 回答