使用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>

这样就能够最终显示提示信息了,

  1

现在我需要将提示信息随鼠标的移动而移动,网上有实现的方法,不过我这里首先要需要解决怎样获取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

posted @ 2010-09-22 21:23  ringgo  阅读(1401)  评论(2编辑  收藏  举报