您的位置:首页 > 其它

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

2009-09-30 10:10 696 查看
在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)

{

//为AutoCompleteBox和DataGrid填充数据

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/)
版权声明:本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐