簡體   English   中英

在MVVM中兩次調用SelectionChanged的列表框命令

[英]Listbox command for SelectionChanged called twice in MVVM

我有一個具有類別項目的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;
        }
    }

感謝您的建議

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

但是在這種情況下,您最好在SelectedCategory源屬性的設置器中處理選擇更改的邏輯,並從XAML中刪除交互觸發器:

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

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

        CategorySelection();
    }
}

這是MVVM處理選擇更改的方法。

好的,試試這個。

在這里更改:

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

刪除此內容:(mm8所說:“ ...並從XAML中刪除交互觸發器... ”)

<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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM