C# 选择和嵌套列表框的问题 介绍
首先,我为这个模糊的标题道歉,但对于我提出的问题,我想不出更好的表达方式: 我正在开发一个C#/WPF应用程序,需要在UI中显示嵌套列表结构。有一个应该显示的对象列表,但每个对象都有一个子列表(可能为空),其中的对象必须以嵌套方式显示。为了实现这一点,我使用了一个C# 选择和嵌套列表框的问题 介绍,c#,wpf,listbox,selection,C#,Wpf,Listbox,Selection,首先,我为这个模糊的标题道歉,但对于我提出的问题,我想不出更好的表达方式: 我正在开发一个C#/WPF应用程序,需要在UI中显示嵌套列表结构。有一个应该显示的对象列表,但每个对象都有一个子列表(可能为空),其中的对象必须以嵌套方式显示。为了实现这一点,我使用了一个ListBox,它有一个包含嵌套ListBox的项目模板来显示子列表 我已经实现了确保一次只能选择一个项目(无论是外部项目还是内部项目)的目标,但我现在正在努力解决以下两个问题,我需要一些帮助: 我需要一种方法来禁用某些项目的选择,以及
ListBox
,它有一个包含嵌套ListBox
的项目模板来显示子列表
我已经实现了确保一次只能选择一个项目(无论是外部项目还是内部项目)的目标,但我现在正在努力解决以下两个问题,我需要一些帮助:
工具提示
ListBoxItem
上时,禁用突出显示外部ListBoxItem
。因此,一次只能在一个ListBoxItem
上高亮显示,尽管高亮显示外部ListBoxItem
也可能会在内部子列表上高亮显示例子 下面是运行我组合的示例所需的两个文件: main window.xaml
<Window x:Class="WpfApplication1.MainWindow"
x:Name="TopLevelWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:local="clr-namespace:WpfApplication1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<ScrollViewer>
<ScrollViewer.Resources>
<local:InvertConverter x:Key="InvertConverter"/>
<CollectionViewSource Source="{Binding Items}" x:Key="ItemsView">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="BoolProperty" Direction="Descending"/>
<scm:SortDescription PropertyName="Text" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="ItemTemplate">
<DockPanel Margin="4,4,2,4"
LastChildFill="True">
<TextBlock Text="{Binding Text}"
DockPanel.Dock="Top"
ToolTip="ERROR"
ToolTipService.IsEnabled="{Binding BoolProperty,
Converter={StaticResource InvertConverter}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding BoolProperty}" Value="False">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ListBox x:Name="InnerListBox"
ItemsSource="{Binding Items}"
SelectedItem="{Binding ElementName=TopLevelWindow,
Path=DataContext.SelectedInnerItem}"
BorderThickness="0"
Background="Transparent"
MouseEnter="InnerListBox_MouseEnter"
MouseLeave="InnerListBox_MouseLeave"/>
</DockPanel>
</DataTemplate>
</ScrollViewer.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource ItemsView}}"
ItemTemplate="{StaticResource ItemTemplate}"
SelectedItem="{Binding SelectedOuterItem}"
BorderThickness="0"/>
</ScrollViewer>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private OuterClass _selectedOuterItem;
private string _selectedInnerItem;
public ObservableCollection<OuterClass> Items { get; set; }
public OuterClass SelectedOuterItem
{
get { return _selectedOuterItem; }
set
{
if (_selectedOuterItem != value)
{
_selectedOuterItem = value;
_selectedInnerItem = null;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedOuterItem)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedInnerItem)));
}
}
}
public string SelectedInnerItem
{
get { return _selectedInnerItem; }
set
{
if (_selectedInnerItem != value)
{
_selectedInnerItem = value;
_selectedOuterItem = null;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedInnerItem)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedOuterItem)));
}
}
}
public MainWindow()
{
Items = new ObservableCollection<OuterClass>()
{
new OuterClass("Beep", true, new List<string>()
{
"Beep - A",
"Beep - B",
"Beep - C"
}),
new OuterClass("Boop", true, new List<string>()
{
"Boop - A",
"Boop - B"
}),
new OuterClass("Baap", false, new List<string>()),
new OuterClass("Biip", true, new List<string>()),
new OuterClass("Buup", false, new List<string>()
{
"Buup - A",
"Buup - B",
"Buup - C",
"Buup - D",
"Buup - E"
})
};
InitializeComponent();
}
private void InnerListBox_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
ListBox listBox = e.Source as ListBox;
if (listBox != null)
{
OuterClass dc = listBox.DataContext as OuterClass;
if (dc != null)
{
dc.MouseOverInternal = true;
}
}
}
private void InnerListBox_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
ListBox listBox = e.Source as ListBox;
if (listBox != null)
{
OuterClass dc = listBox.DataContext as OuterClass;
if (dc != null)
{
dc.MouseOverInternal = false;
}
}
}
}
public class OuterClass : INotifyPropertyChanged
{
private bool _mouseOverInternal;
public string Text { get; set; }
public bool BoolProperty { get; set; }
public ObservableCollection<string> Items { get; set; }
public bool MouseOverInternal
{
get { return _mouseOverInternal; }
set
{
if (_mouseOverInternal != value)
{
_mouseOverInternal = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MouseOverInternal)));
}
}
}
public OuterClass(string x, bool y, IEnumerable<string> z)
{
Text = x;
BoolProperty = y;
Items = new ObservableCollection<string>(z);
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class InvertConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return foo(value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return foo(value);
}
private bool? foo(object val)
{
bool? boolVal = val as bool?;
if (boolVal.HasValue)
{
return !boolVal.Value;
}
return null;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
利用制度全球化;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
命名空间WpfApplication1
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口,INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
专用外部类\u选择外部项;
私有字符串\u选择的子项;
公共ObservableCollection项{get;set;}
public OuterClass SelectedOutItem
{
获取{return\u selectedOutItem;}
设置
{
如果(_selectedOutItem!=值)
{
_SelectedOutItem=值;
_selectedInnerItem=null;
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称)(SelectedOutItem));
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称)(SelectedInnerItem));
}
}
}
公共字符串SelectedInnerItem
{
获取{return\u selectedInnerItem;}
设置
{
如果(_selectedInnerItem!=值)
{
_selectedInnerItem=值;
_SelectedOutItem=null;
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称)(SelectedInnerItem));
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称)(SelectedOutItem));
}
}
}
公共主窗口()
{
Items=新的ObservableCollection()
{
新的外部类(“嘟嘟声”,正确,新列表()
{
“哔-A”,
“哔-B”,
“哔-C”
}),
新的外部类(“Boop”,真,新列表()
{
“Boop-A”,
“Boop-B”
}),
新建外部类(“Baap”,false,new List()),
新的外部类(“Biip”,true,new List()),
新外部类(“Buup”,false,新列表()
{
“Buup-A”,
“Buup-B”,
“Buup-C”,
“Buup-D”,
“Buup-E”
})
};
初始化组件();
}
private void InnerListBox_MouseEnter(对象发送方,System.Windows.Input.MouseEventArgs e)
{
ListBox ListBox=e.源为ListBox;
如果(列表框!=null)
{
OuterClass dc=listBox.DataContext作为OuterClass;
如果(dc!=null)
{
dc.MouseOverInternal=true;
}
}
}
私有void InnerListBox_MouseLeave(对象发送方,System.Windows.Input.MouseEventArgs e)
{
ListBox ListBox=e.源为ListBox;
如果(列表框!=null)
{
OuterClass dc=listBox.DataContext作为OuterClass;
如果(dc!=null)
{
dc.MouseOverInternal=false;
}
}
}
}
公共类外部类:INotifyPropertyChanged
{
私人布勒(mouseOverInternal),;
公共字符串文本{get;set;}
公共布尔布尔属性{get;set;}
公共ObservableCollection项{get;set;}
公共布尔鼠标内部
{
获取{return\u mouseOverInternal;}
设置
{
if(_mouseOverInternal!=值)
{
_mouseOverInternal=值;
PropertyChanged?.Invoke(这是新的propertychangedventargs(nameof(MouseOverInternal));
}
}
}
公共外部类(字符串x、布尔y、IEnumerable z)
{
Text=x;
BoolProperty=y;
项目=新观测值a