我有一个列表框,其中包含某些项(已绑定),其中某些项是其他项的“子项”,非常类似于VS 2017中的“调试->选项”窗口的样子。我试图做另一件事就是,当选择父项时,我希望列表框选择该父项的第一个孩子。
当我单击一个孩子时,该孩子表现良好,在这种情况下当然不需要进行任何更新。但是,当我单击父级时,尽管右侧操作正确(看到选定的子级),但列表框仍显示所选的父级。
我可以在构造函数中设置SelectedPane,它可以正确更新列表框。
我已将内容简化为(大多数)裸代码以进行复制。
我的XAML:
<Window x:Class="WPF_Scratch.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:local="clr-namespace:WPF_Scratch"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:MainVM x:Key="main"/>
</Window.Resources>
<Window.DataContext>
<Binding Source="{StaticResource main}"/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" ItemsSource="{Binding Panes}"
SelectedItem="{Binding SelectePane, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.Style>
<Style>
<Setter Property="Control.Margin" Value="0,0,0,0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Indent}" Value="True">
<Setter Property="Control.Margin" Value="10,0,0,0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Column="1" Text="{Binding Path=SelectePane.Name}"/>
</Grid>
</Window>
以及背后的代码:
using System.Collections.Generic;
using System.ComponentModel;
namespace WPF_Scratch
{
public class NotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void _UpdateField<T>(ref T field, T newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
_OnPropertyChanged(propertyName);
}
}
protected virtual void _OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainVM: NotifyPropertyChanged
{
public class PaneInfo
{
public string Name { get; set; }
public PaneInfo Child { get; set; }
public bool Indent { get; set; }
}
private PaneInfo[] _panes;
public PaneInfo[] Panes => _panes;
private PaneInfo _selectedPane;
public PaneInfo SelectePane
{
get => _selectedPane;
set
{
if (value?.Child != null)
{
//SelectePane = value.Child;
_UpdateField(ref _selectedPane, value.Child);
}
else
_UpdateField(ref _selectedPane, value);
}
}
public MainVM()
{
PaneInfo childOne = new PaneInfo { Name = "Child One", Indent = true };
PaneInfo parentOne = new PaneInfo { Name = "Parent One", Child = childOne };
PaneInfo childTwo = new PaneInfo { Name = "Child Two", Indent = true };
PaneInfo parentTwo = new PaneInfo { Name = "Parent Two", Child = childTwo };
_panes = new PaneInfo[4]
{
parentOne, childOne, parentTwo, childTwo
};
}
}
}
谢谢