SelectionVhanged的Listbox命令在MVVM中调用两次

时间:2017-12-11 11:51:08

标签: c# wpf mvvm listbox command

我有一个包含类别项的ListBox。当我点击一个类别时,我希望子类别到达。但是当我选择一个类别时,SelectionChanged 方法调用了两次。我无法通过调试处理这种情况。如果我将断点放到CategorySelection方法中,则此问题不会重复。

Categories.xaml

<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" BorderThickness="0">
                    <ListBox VerticalAlignment="Top" ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}" ItemContainerStyle="{StaticResource CategoryItemStyle}" Padding="-3,0,-3,0" Height="250" BorderThickness="0" >
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="SelectionChanged">
                                <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Border Name="brd_bindCategories" HorizontalAlignment="Stretch" Style="{StaticResource categoryborder}" >
                                    <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  ShowGridLines="True">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                                            <ColumnDefinition Width="*"></ColumnDefinition>
                                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition></RowDefinition>
                                            <RowDefinition></RowDefinition>
                                        </Grid.RowDefinitions>
                                        <Image  Source="/Launcher;component/Images/WhiteArrowRight.png" Margin="5,0,0,0" />

                                        <StackPanel Orientation="Horizontal" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
                                            <Image Name="img_endItem" Source="{Binding imagePath}" Margin="0,0,10,5" Width="24" Height="24" HorizontalAlignment="Right" ></Image>
                                            <Label  x:Name="lbl_operationName"  FontWeight="Normal" Content="{Binding category_name}" FontSize="21" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}, Path=Foreground}">
                                                <Label.ToolTip>
                                                    <ToolTip Visibility="{Binding Path=expansion, Converter={StaticResource StringToVisibilityConverter}}">
                                                        <Grid>
                                                            <TextBlock Text="{Binding Path=expansion}" />
                                                        </Grid>
                                                    </ToolTip>
                                                </Label.ToolTip>
                                            </Label>
                                        </StackPanel>

                                        <Image  Grid.Column="2" Source="..\Images\WhiteArrowLeft.png" Margin="0,0,15,0"/>
                                        <Line Grid.Column="2" Grid.Row="1" Fill="Black" HorizontalAlignment="Stretch" Height="2"></Line>
                                    </Grid>
                                </Border>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                        <ListBox.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Vertical" />
                            </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
                    </ListBox>

                </ScrollViewer>

一些代码进入CategoriesViewModel.cs

 public ICommand SelectionChangedCommand { get; set; }
 private ObservableCollection<Category> _categories { get; set; }
    public ObservableCollection<Category> Categories
    {
        get
        {
            return _categories;
        }
        set
        {
            _categories = value;
            RaisePropertyChanged(nameof(Categories));
        }
    }

    public Category PreviousSelectedCategory { get; set; }

    Category _selectedCategory { get; set; }
    public Category SelectedCategory
    {
        get
        {
            return _selectedCategory;
        }
        set
        {
            if (value != null)
            {
                PreviousSelectedCategory = value;
            }

            _selectedCategory = value;
            RaisePropertyChanged(nameof(SelectedCategory));


        }
    }

    private ObservableCollection<Category> _tempcategories { get; set; }
    public ObservableCollection<Category> TempCategories
    {
        get
        {
            return _tempcategories;
        }
        set
        {
            _tempcategories = value;
            RaisePropertyChanged(nameof(TempCategories));
        }
    }
public CategoriesViewModel(MainTemplateViewModel ViewModel)

    {

        SelectionChangedCommand = DelegateCommandFactory.CreateAutoInvalidate(CategorySelection);
    }

和一些方法

private void CategorySelection()
    {
        SearchText = string.Empty;
        mainTempVM.IsOpenUserProfil = false;

        if (SelectedCategory != null)
        {
            var selectedCategoryName = SelectedCategory.category_name;

            if (selectedCategoryName == OtherConstans.AircraftSystems)
            {
                mainTempVM.ActiveMenu = MainTemplateViewModel.Menus.MENU2;
                Title = OtherConstans.AnkaHaSystemsVmtModule;
            }
            else if (selectedCategoryName == OtherConstans.GroundSystems)
            {
                int index = Array.IndexOf(Enum.GetValues(typeof(MainTemplateViewModel.Menus)), mainTempVM.ActiveMenu);
                mainTempVM.ActiveMenu = Enum.GetValues(typeof(MainTemplateViewModel.Menus)).Cast<MainTemplateViewModel.Menus>().First(e => (int)e >= (int)index);

                mainTempVM.Menu3Text = selectedCategoryName.Replace(OtherConstans.AnkaHA, string.Empty);
                Title = selectedCategoryName + Punctuations.Blank.Symbol + OtherConstans.Applications;

                mainTempVM.Menu3TextTag = selectedCategoryName + Punctuations.Blank.Symbol + OtherConstans.Applications;
            }
            else
            {

                if (selectedCategoryName == OtherConstans.MechanicalSystems || selectedCategoryName == OtherConstans.AvionicsSystems ||
                    selectedCategoryName == OtherConstans.GeneralProcedures || selectedCategoryName == OtherConstans.PropulsionSystems ||
                    selectedCategoryName == OtherConstans.StructuralSystems)
                {
                    mainTempVM.ActiveMenu = MainTemplateViewModel.Menus.MENU3;

                    mainTempVM.Menu3Text = selectedCategoryName.Replace(OtherConstans.AnkaHA, string.Empty);

                    Title = selectedCategoryName + Punctuations.Blank.Symbol + OtherConstans.Applications;

                    mainTempVM.Menu3TextTag = selectedCategoryName + Punctuations.Blank.Symbol + OtherConstans.Applications;

                }
                else if (selectedCategoryName == OtherConstans.RemovalInstallationOperations || selectedCategoryName == OtherConstans.FaultIsolationRepairOperations ||
                    selectedCategoryName == OtherConstans.TestOperations || selectedCategoryName == OtherConstans.AdjustmentAndCalibrationOperations ||
                    selectedCategoryName == OtherConstans.SoftwareAndDataOperations)
                {
                    mainTempVM.ActiveMenu = MainTemplateViewModel.Menus.MENU4;

                    var words = selectedCategoryName;
                    string[] final = words.Split('-');
                    Title = selectedCategoryName;

                    var tab = words.Replace(Punctuations.Dash.Symbol, string.Empty);
                    mainTempVM.Menu4Text = tab.Replace(OtherConstans.Operations, string.Empty);
                    mainTempVM.Menu4TextTag = selectedCategoryName;


                }
                else
                {
                    mainTempVM.ActiveMenu = MainTemplateViewModel.Menus.MENU4;

                    var userRole = LauncherCommunicator.Instance.Session.userRole;
                    mainTempVM.ActivePage = userRole == OtherConstans.Instructor ? MainTemplateViewModel.Pages.JobAssignmentInstructor : MainTemplateViewModel.Pages.JobAssignmentTrainee;


                    mainTempVM.JobAssignmentVM.ScenarioSearchText = string.Empty;
                    var previousTitle = mainTempVM.Menu4TextTag;

                    mainTempVM.JobAssignmentVM.Title = selectedCategoryName + Punctuations.Blank.Symbol + previousTitle;
                    mainTempVM.Menu4Text = previousTitle.ToString().Replace(Punctuations.Dash.Symbol, string.Empty);

                    mainTempVM.JobAssignmentVM.GetScenarios();
                    mainTempVM.JobAssignmentVM.SetVisiblitiesByUserRole();
                    mainTempVM.JobAssignmentVM.GetTrainees();

                }


            }
            GetChildCategoryList();

        }
    }

    public void GetChildCategoryList()
    {
        var selectedCategoryId = SelectedCategory == null ? 0 : SelectedCategory.category_id;

        List<DataStructureForWebService.Category> categoriesList;
        if (LauncherCommunicator.Instance.GetCategoryList(selectedCategoryId, out categoriesList))
        {
            var categories = categoriesList.OrderBy(i => i.category_name);
            Categories = new ObservableCollection<Category>(categories);
            TempCategories = Categories;
        }
        else
        {
            Categories = new ObservableCollection<Category>();
            TempCategories = Categories;
        }

        if (mainTempVM.ActiveMenu == MainTemplateViewModel.Menus.MENU3)
        {
            mainTempVM.Menu3Tag = TempCategories;
        }
    }

感谢您的建议

2 个答案:

答案 0 :(得分:0)

SelectionChanged是一个路由事件。因此,它可能由ListBox的子元素以及ListBox本身引发。

但是在这种情况下,你也可以在SelectedCategory source属性的setter中处理你的选择更改逻辑,并从你的XAML中删除交互触发器:

Category _selectedCategory;
public Category SelectedCategory
{
    get
    {
        return _selectedCategory;
    }
    set
    {
        if (value != null)
        {
            PreviousSelectedCategory = value;
        }

        _selectedCategory = value;
        RaisePropertyChanged(nameof(SelectedCategory));

        CategorySelection();
    }
}

这是处理选择更改的MVVM方式。

答案 1 :(得分:0)

好的,试试这个。

在此处更改:

<ListBox .... SelectedItem="{Binding SelectedCategory, UpdateSourceTrigger=PropertyChanged}" .... >

删除此内容(正如 mm8 &#34; ...所说的那样,并从您的XAML中删除交互触发器...... &#34)

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

在此处,您将在执行方法CategorySelection之前检查类别是否已更改

Category _selectedCategory;
public Category SelectedCategory
{
    get
    {
        return _selectedCategory;
    }
    set
    {
        if (_selectedCategory == value) 
            return;

        if (value != null)
            PreviousSelectedCategory = value;

        _selectedCategory = value;
        RaisePropertyChanged(nameof(SelectedCategory));

        CategorySelection();
    }
}