有关AutoCompleteBox组件的研究[4]_下拉框内嵌DataGrid与被嵌入DataGrid——Silverlight学习笔记[39]...

AutoCompleteBox组件下拉框中嵌入DataGrid可以让我们更好地组织候选数据以达到更好的显示效果。与此类似的,在DataGrid组件中嵌入AutoCompleteBox组件可以便于我们进行数据的输入。本文将为大家讲述如何实现这两种效果。

 

※内嵌DataGrid

为了能实现在AutoCompleteBox组件的下拉框中成功地嵌入DataGrid,我们需要用到微软提供给我们的一个辅助类DataGridSelectionAdapter,该类继承自DataGrid并实现了ISelectionAdapter接口。该类的代码如下:

DataGridSelectionAdapter.cs(将该文件保存在Silverlight项目文件夹下)

using System;

using System.Collections;

using System.Collections.ObjectModel;

using System.Collections.Specialized;

using System.Windows;

using System.Windows.Automation.Peers;

using System.Windows.Controls;

using System.Windows.Input;

 

namespace SilverlightClient

{

    public class DataGridSelectionAdapter : DataGrid, ISelectionAdapter

    {

        private bool IgnoreAnySelection { get; set; }

        private bool IgnoringSelectionChanged { get; set; }

        public new event SelectionChangedEventHandler SelectionChanged;

        public event RoutedEventHandler Commit;

        public event RoutedEventHandler Cancel;

 

        public DataGridSelectionAdapter()

        {

            base.SelectionChanged += OnSelectionChanged;

            MouseLeftButtonUp += OnSelectorMouseLeftButtonUp;

        }

 

        public new object SelectedItem

        {

            get

            {

                return base.SelectedItem;

            }

            set

            {

                IgnoringSelectionChanged = true;

                base.SelectedItem = value;

                IgnoringSelectionChanged = false;

            }

        }

 

        private void OnSelectorMouseLeftButtonUp(object sender, MouseButtonEventArgs e)

        {

            IgnoreAnySelection = false;

 

            OnSelectionChanged(this, null);

            OnCommit(this, new RoutedEventArgs());

        }

 

        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            if (IgnoringSelectionChanged)

            {

                return;

            }

 

            if (IgnoreAnySelection)

            {

                return;

            }

 

            SelectionChangedEventHandler handler = this.SelectionChanged;

            if (handler != null)

            {

                handler(sender, e);

            }

        }

 

        public new IEnumerable ItemsSource

        {

            get { return base.ItemsSource; }

           

            set

            {

                if (base.ItemsSource != null)

                {

                    INotifyCollectionChanged notify = base.ItemsSource as INotifyCollectionChanged;

                    if (notify != null)

                    {

                        notify.CollectionChanged -= OnCollectionChanged;

                    }

                }

 

                base.ItemsSource = value;

 

                if (base.ItemsSource != null)

                {

                    INotifyCollectionChanged notify = base.ItemsSource as INotifyCollectionChanged;

                    if (notify != null)

                    {

                        notify.CollectionChanged += OnCollectionChanged;

                    }

                }

            }

        }

 

        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

        {

            IgnoreAnySelection = true;

        }

 

        private ObservableCollection<object> Items

        {

            get { return ItemsSource as ObservableCollection<object>; }

        }

 

        private void SelectedIndexIncrement()

        {

            SelectedIndex = SelectedIndex + 1 >= Items.Count ? -1 : SelectedIndex + 1;

            ScrollIntoView(SelectedItem, this.Columns[0]);

        }

 

        private void SelectedIndexDecrement()

        {

            int index = SelectedIndex;

            if (index >= 0)

            {

                SelectedIndex--;

            }

            else if (index == -1)

            {

                SelectedIndex = Items.Count - 1;

            }

 

            ScrollIntoView(SelectedItem, this.Columns[0]);

        }

 

        public void HandleKeyDown(KeyEventArgs e)

        {

            switch (e.Key)

            {

                case Key.Enter:

                    OnCommit(this, e);

                    e.Handled = true;

                    break;

 

                case Key.Up:

                    IgnoreAnySelection = false;

                    SelectedIndexDecrement();

                    e.Handled = true;

                    break;

 

                case Key.Down:

                    if ((ModifierKeys.Alt & Keyboard.Modifiers) == ModifierKeys.None)

                    {

                        IgnoreAnySelection = false;

                        SelectedIndexIncrement();

                        e.Handled = true;

                    }

                    break;

 

                case Key.Escape:

                    OnCancel(this, e);

                    e.Handled = true;

                    break;

 

                default:

                    break;

            }

        }

 

        private void OnCommit(object sender, RoutedEventArgs e)

        {

            RoutedEventHandler handler = Commit;

            if (handler != null)

            {

                handler(sender, e);

            }

 

            AfterAdapterAction();

        }

 

        private void OnCancel(object sender, RoutedEventArgs e)

        {

            RoutedEventHandler handler = Cancel;

            if (handler != null)

            {

                handler(sender, e);

            }

 

            AfterAdapterAction();

        }

 

        private void AfterAdapterAction()

        {

            IgnoringSelectionChanged = true;

            SelectedItem = null;

            SelectedIndex = -1;

            IgnoringSelectionChanged = false;

 

            // Reset, to ignore any future changes

            IgnoreAnySelection = true;

        }

 

        public AutomationPeer CreateAutomationPeer()

        {

            return new DataGridAutomationPeer(this);

        }

    }

}

 

DataGrid中嵌入AutoCompleteBox

主要用到的方法是使用DataGrid组件中的DataGridTemplateColumn标签。

 

完整的实例代码:

详细的说明在代码注释中给出。

MainPage.xaml文件代码

<UserControl

    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:samples="clr-namespace:SilverlightClient"

    mc:Ignorable="d" xmlns:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="SilverlightClient.MainPage"

    d:DesignWidth="320" d:DesignHeight="480">

    <Grid x:Name="LayoutRoot" Width="320" Height="480" Background="White">

    <Grid.Resources>

        <!--AutoCompleteBox组件数据网格样式设定-->

        <Style x:Key="DataGridAutoCompleteTemplate" TargetType="input:AutoCompleteBox">

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="input:AutoCompleteBox">

                        <Grid>

                                <VisualStateManager.VisualStateGroups>

                                    <VisualStateGroup x:Name="PopupStates">

                                        <VisualStateGroup.Transitions>

                                            <VisualTransition GeneratedDuration="0:0:0.2" To="PopupOpened" />

                                            <VisualTransition GeneratedDuration="0:0:0.2" To="PopupClosed" />

                                        </VisualStateGroup.Transitions>

                                        <VisualState x:Name="PopupOpened">

                                            <Storyboard>

                                                <DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="1.0" />

                                            </Storyboard>

                                        </VisualState>

                                        <VisualState x:Name="PopupClosed">

                                            <Storyboard>

                                                <DoubleAnimation Storyboard.TargetName="PopupBorder" Storyboard.TargetProperty="Opacity" To="0.0" />

                                            </Storyboard>

                                        </VisualState>

                                    </VisualStateGroup>

                                </VisualStateManager.VisualStateGroups>

                                <TextBox IsTabStop="True" x:Name="Text" Margin="0" />

                                <Popup x:Name="Popup">

                                    <Border x:Name="PopupBorder" HorizontalAlignment="Stretch" Opacity="0.0" BorderThickness="0" CornerRadius="3">

                                        <Border.RenderTransform>

                                            <TranslateTransform X="2" Y="2" />

                                        </Border.RenderTransform>

                                        <Border.Background>

                                            <SolidColorBrush Color="#11000000" />

                                        </Border.Background>

                                        <Border HorizontalAlignment="Stretch" BorderThickness="0" CornerRadius="3">

                                            <Border.Background>

                                                <SolidColorBrush Color="#11000000" />

                                            </Border.Background>

                                            <Border.RenderTransform>

                                                <TransformGroup>

                                                    <ScaleTransform />

                                                    <SkewTransform />

                                                    <RotateTransform />

                                                    <TranslateTransform X="-1" Y="-1" />

                                                </TransformGroup>

                                            </Border.RenderTransform>

                                            <Border HorizontalAlignment="Stretch" Opacity="1.0" Padding="1" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3">

                                                <Border.RenderTransform>

                                                    <TransformGroup>

                                                        <ScaleTransform />

                                                        <SkewTransform />

                                                        <RotateTransform />

                                                        <TranslateTransform X="-2" Y="-2" />

                                                    </TransformGroup>

                                                </Border.RenderTransform>

                                                <Border.Background>

                                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                                                        <GradientStop Color="#FFDDDDDD" Offset="0"/>

                                                        <GradientStop Color="#AADDDDDD" Offset="1"/>

                                                    </LinearGradientBrush>

                                                </Border.Background>

                                                <!--DataGridSelectionAdapter绑定数据字段-->

                                                <samples:DataGridSelectionAdapter

                                                x:Name="SelectionAdapter"

                                                AutoGenerateColumns="False"

                                                IsReadOnly="True" FontSize="14">

                                                    <samples:DataGridSelectionAdapter.Columns>

                                                        <data:DataGridTextColumn Header="员工号" Binding="{Binding EmployeeID}" />

                                                        <data:DataGridTextColumn Header="员工姓名" Binding="{Binding EmployeeName}" />

                                                        <data:DataGridTextColumn Header="员工年龄" Binding="{Binding EmployeeAge}" />

                                                    </samples:DataGridSelectionAdapter.Columns>

                                                </samples:DataGridSelectionAdapter>

                                            </Border>

                                        </Border>

                                    </Border>

                                </Popup>

                            </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

    </Grid.Resources>

        <input:AutoCompleteBox x:Name="acb" Height="26" Margin="8,32,132,0" VerticalAlignment="Top" Style="{StaticResource DataGridAutoCompleteTemplate}" ValueMemberBinding="{Binding EmployeeName}"/>

        <data:DataGrid x:Name="dgEmployee" Height="209" Margin="8,0,8,8" VerticalAlignment="Bottom" AutoGenerateColumns="False" FontSize="14">

            <data:DataGrid.Columns>

                <data:DataGridTextColumn Header="员工号" Binding="{Binding EmployeeID}" IsReadOnly="True" />

                <data:DataGridTemplateColumn Header="员工姓名" Width="90">

                    <!--设置AutoCompleteBox模板-->

                    <data:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock Text="{Binding EmployeeName,Mode=TwoWay}"/>

                        </DataTemplate>

                    </data:DataGridTemplateColumn.CellTemplate>

                    <data:DataGridTemplateColumn.CellEditingTemplate>

                        <DataTemplate>

                            <input:AutoCompleteBox x:Name="embeddedACB" Text="{Binding EmployeeName,Mode=TwoWay}" ValueMemberPath="EmployeeName" Loaded="embeddedACB_Loaded" Width="90">

                                <input:AutoCompleteBox.ItemTemplate>

                                    <DataTemplate>

                                        <TextBlock Text="{Binding EmployeeName}"/>

                                    </DataTemplate>

                                </input:AutoCompleteBox.ItemTemplate>

                            </input:AutoCompleteBox>

                        </DataTemplate>

                    </data:DataGridTemplateColumn.CellEditingTemplate>

                </data:DataGridTemplateColumn>

                <data:DataGridTextColumn Header="员工年龄" Binding="{Binding EmployeeAge,Mode=TwoWay}" />

            </data:DataGrid.Columns>

        </data:DataGrid>

    </Grid>

</UserControl>

 

MainPage.xaml.cs文件代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Controls.Common;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

using System.ComponentModel;

 

namespace SilverlightClient

{

    //业务对象类

    public class Employees

    {

        public int EmployeeID { get; set; }

        public string EmployeeName { get; set; }

        public int EmployeeAge { get; set; }

    }

   

    public partial class MainPage : UserControl

    {

        public MainPage()

        {

            InitializeComponent();

            //注册事件触发

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

        }

 

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            //AutoCompleteBoxDataGrid填充数据

            acb.ItemsSource = GetEmployees();

            acb.FilterMode = AutoCompleteFilterMode.Contains;

            dgEmployee.ItemsSource = GetEmployees();

        }

 

        //DataGrid组件中的AutoCompleteBox组件提供数据

        void embeddedACB_Loaded(object sender, RoutedEventArgs e)

        {

            AutoCompleteBox myacb = sender as AutoCompleteBox;

            myacb.ItemsSource = GetEmployees();

        }

 

        //数据源

        ObjectCollection GetEmployees()

        {

            ObjectCollection returnedValue = new ObjectCollection();

            returnedValue.Add(new Employees() { EmployeeID = 1, EmployeeName = "Alice", EmployeeAge = 21 });

            returnedValue.Add(new Employees() { EmployeeID = 2, EmployeeName = "Allen", EmployeeAge = 22 });

            returnedValue.Add(new Employees() { EmployeeID = 3, EmployeeName = "Benedict", EmployeeAge = 23 });

            returnedValue.Add(new Employees() { EmployeeID = 4, EmployeeName = "Ben", EmployeeAge = 24 });

            returnedValue.Add(new Employees() { EmployeeID = 5, EmployeeName = "Black", EmployeeAge = 25 });

            returnedValue.Add(new Employees() { EmployeeID = 6, EmployeeName = "Charles", EmployeeAge = 26 });

            returnedValue.Add(new Employees() { EmployeeID = 7, EmployeeName = "Chasel", EmployeeAge = 27 });

            returnedValue.Add(new Employees() { EmployeeID = 8, EmployeeName = "Dave", EmployeeAge = 28 });

            returnedValue.Add(new Employees() { EmployeeID = 9, EmployeeName = "David", EmployeeAge = 29 });

            returnedValue.Add(new Employees() { EmployeeID = 10, EmployeeName = "Dean", EmployeeAge = 30 });

            return returnedValue;

        }

    }

}

 

最终效果图:

 

作者:Kinglee
文章出处:Kinglee’s Blog ( http://www.cnblogs.com/Kinglee/)
版权声明:本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值