我有一个包含类别项的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;
}
}
感谢您的建议
答案 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();
}
}