使用ListBox中遇到的问题
这几天一直与ListBox打交道,对ListBox的了解也加深了一层,这篇文章把相关的思路写下来,为了简化起见,省略了一些无关重要的东西
首先声明数据源对象,这里以一个简单的类为例
public class Person{public string FirstName { get; set; }public string LastName { get; set; }}public class People : ObservableCollection<Person>{public List<Person> Detailes { get; set; }public People()
{Detailes = new List<Person>
{new Person{FirstName="David",LastName="White"},new Person{FirstName="Jim",LastName="Green"},new Person{FirstName="Tom",LastName="Polly"}};}}
数据源已经建立好了,现在将其绑定到ListBox中,这里需要横向绑定,SDK中有横向绑定的实现,这里就不再进行细说,按照需求,当鼠标移到FirstName时提示关于LastName的信息,才开始做的时候总是无法显示提示信息,然后在网上找到了原因:附加属性ToolTipService.ToolTip并没有继承上层元素的DataContext
原因找到了,解决思路就清晰了,先声明一个值转换器
public class MyConvert : IValueConverter{public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture){if (value != null){var str = value.ToString();
TextBlock tb = new TextBlock();
tb.Text = str;return tb;
}return null;}...}
将相关的类声明为资源
<loacls:People x:Key="people"></loacls:People><loacls:MyConvert x:Key="convert"></loacls:MyConvert>
Xaml代码:
<Grid DataContext="{StaticResource people}" ><ListBox ItemsSource="{Binding Detailes}"ScrollViewer.VerticalScrollBarVisibility="Hidden"><ItemsControl.ItemsPanel><ItemsPanelTemplate><StackPanel Orientation="Horizontal"></StackPanel></ItemsPanelTemplate></ItemsControl.ItemsPanel><ListBox.ItemTemplate><DataTemplate><Grid><TextBlock Text="{Binding FirstName}" ToolTipService.Placement="Mouse"
ToolTipService.ToolTip="{Binding LastName,Converter={StaticResource convert}}" />
</Grid></DataTemplate></ListBox.ItemTemplate></ListBox></Grid>
这样就能够最终显示提示信息了,
现在我需要将提示信息随鼠标的移动而移动,网上有实现的方法,不过我这里首先要需要解决怎样获取DataTemplate内的控件
<TextBlock x:Name="myTxt" MouseMove="TextBlock_MouseMove" FontFamily="Arial" Foreground="#333333" FontSize="18" Text="{Binding FirstName}"><ToolTipService.ToolTip><ToolTip x:Name="tip" Placement="Mouse"><Binding Path="LastName" Converter="{StaticResource convert}"></Binding></ToolTip></ToolTipService.ToolTip></TextBlock>
DataTemplate进行了一些改动,那么我需要先获取TextBlock,再获取其中的ToolTip,这个部分参考了园里这篇文章,当鼠标在TextBlock移动时,就进行下面的处理:
private void TextBlock_MouseMove(object sender, MouseEventArgs e){double x;
Random random = new Random();
x = e.GetPosition(null).X;
ListBoxItem _selectedItem;if (this.listBox1.SelectedItem != null){_selectedItem = (ListBoxItem)(this.listBox1.ItemContainerGenerator.ContainerFromItem(this.listBox1.SelectedItem));}else
{_selectedItem = (ListBoxItem)(this.listBox1.ItemContainerGenerator.ContainerFromItem(this.listBox1.Items[0]));}TextBlock myTxt = FindFirstVisualChild<TextBlock>(_selectedItem, "myTxt");
ToolTip tip = myTxt.FindName("tip") as ToolTip;if (tip != null){if (x > 5)
{tip.HorizontalOffset = random.Next(1, 3);}else
{tip.HorizontalOffset = x;}}}
获取可视化的代码也贴出来:
public T FindFirstVisualChild<T>(DependencyObject obj,string childName) where T : DependencyObject{for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++){DependencyObject child = VisualTreeHelper.GetChild(obj, i);if (child != null && child is T && child.GetValue(NameProperty).ToString()==childName){return (T)child;
}else
{T childOfChild = FindFirstVisualChild<T>(child,childName);if (childOfChild != null){return childOfChild;
}}}return null;}完成以后,就实现选择ListBox的Item时,提示信息就会跟随鼠标的移动而移动了。其实利用上面的方法,也可以动态的改变listboxItem的背景色
_selectedItem.Background = new SolidColorBrush(Colors.Orange);
上面所讲用到不少的知识点,希望对你有所帮助,不过上面有个地方我总是无法实现,即如DataGrid那样,将ListBoxItem的背景色进行交替变换,我模仿MSDN上改变 ListView 中各行的背景色进行修改,但是没能实现,只好以后如果解决了再贴出来,如果有朋友实现过这个功能,也请不吝赐教!
代码下载:ListBoxExample.rar