Skip to main content
Home Forums Silverlight Programming Silverlight Controls and Silverlight Toolkit AutoCompleteBox: implementing page/up down in popup
3 replies. Latest Post by Mog Liang - MSFT on August 15, 2009.
(0)
kobruleht
Member
161 points
579 Posts
08-08-2009 4:52 AM |
I'm looking for a way to implement page up/down navigation in popup in SL3
http://www.jeff.wilcox.name/2008/12/pageup-pagedown
buto got exception below. How to add page up/down ctrl+home/end navigation to AutoCompleteBox ?
Andrus.
System.Windows.Markup.XamlParseException occurred Message=" [Line: 0 Position: 0]\r\n --- Inner Exception ---\r\nElement is already the child of another element.\r\n" LineNumber=0 LinePosition=0 StackTrace: at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData) InnerException: System.InvalidOperationException Message="Element is already the child of another element." StackTrace: at MS.Internal.XcpImports.CheckHResult(UInt32 hr) at MS.Internal.XcpImports.Collection_AddValue[T](PresentationFrameworkCollection`1 collection, CValue value) at MS.Internal.XcpImports.Collection_AddDependencyObject[T](PresentationFrameworkCollection`1 collection, DependencyObject value) at System.Windows.PresentationFrameworkCollection`1.AddDependencyObject(DependencyObject value) at System.Windows.Controls.UIElementCollection.AddInternal(UIElement value) at System.Windows.PresentationFrameworkCollection`1.Add(T value) at Microsoft.Windows.Controls.AutoCompleteBox.OnApplyTemplate() at CustomAutoCompleteBox.CustomizedAutoCompleteBox.OnApplyTemplate() at System.Windows.FrameworkElement.OnApplyTemplate(IntPtr nativeTarget) InnerException:
Mog Lian...
All-Star
15884 points
1,541 Posts
08-13-2009 11:30 PM |
Hi,
You could find autocompletebox inner listbox by accessing its default template, then by handling autocomplatebox keydown event, you could set selectedindex on listbox.
sample code:
xaml
<UserControl.Resources> <ControlTemplate x:Key="CommonValidationToolTipTemplate" TargetType="ToolTip"> <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="OpenStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0"/> <VisualTransition GeneratedDuration="0:0:0.2" To="Open"> <Storyboard> <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="Translation" Storyboard.TargetProperty="X" To="0"> <DoubleAnimation.EasingFunction> <BackEase Amplitude=".3" EasingMode="EaseOut"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1"/> </Storyboard> </VisualTransition> </VisualStateGroup.Transitions> <VisualState x:Name="Closed"> <Storyboard> <DoubleAnimation Duration="0" Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="0"/> </Storyboard> </VisualState> <VisualState x:Name="Open"> <Storyboard> <DoubleAnimation Duration="0" Storyboard.TargetName="Translation" Storyboard.TargetProperty="X" To="0"/> <DoubleAnimation Duration="0" Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity" To="1"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid.RenderTransform> <TranslateTransform x:Name="Translation" X="-25"/> </Grid.RenderTransform> <Border Margin="4,4,-4,-4" Background="#052A2E31" CornerRadius="5"/> <Border Margin="3,3,-3,-3" Background="#152A2E31" CornerRadius="4"/> <Border Margin="2,2,-2,-2" Background="#252A2E31" CornerRadius="3"/> <Border Margin="1,1,-1,-1" Background="#352A2E31" CornerRadius="2"/> <Border Background="#FFDC000C" CornerRadius="2"> <TextBlock Margin="8,4,8,4" MaxWidth="250" UseLayoutRounding="false" Foreground="#FFFFFFFF" Text="{Binding (Validation.Errors)[0].Exception.Message}" TextWrapping="Wrap"/> </Border> </Grid> </ControlTemplate> <Style x:Key="AutoCompleteBoxStyle1" TargetType="input:AutoCompleteBox"> <Setter Property="IsTabStop" Value="False"/> <Setter Property="Padding" Value="2"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush"> <Setter.Value> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFA3AEB9" Offset="0"/> <GradientStop Color="#FF8399A9" Offset="0.375"/> <GradientStop Color="#FF718597" Offset="0.375"/> <GradientStop Color="#FF617584" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="Background" Value="#FFFFFFFF"/> <Setter Property="Foreground" Value="#FF000000"/> <Setter Property="MinWidth" Value="45"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="input:AutoCompleteBox"> <Grid Opacity="{TemplateBinding Opacity}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="PopupStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0:0:0.1" 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> <VisualStateGroup x:Name="ValidationStates"> <VisualState x:Name="Valid"/> <VisualState x:Name="InvalidUnfocused"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="InvalidFocused"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <System:Boolean>True</System:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBox x:Name="Text" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Foreground="{TemplateBinding Foreground}" IsTabStop="True" Padding="{TemplateBinding Padding}" Margin="0" Style="{TemplateBinding TextBoxStyle}"/> <Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1"> <ToolTipService.ToolTip> <ToolTip x:Name="validationTooltip" Template="{StaticResource CommonValidationToolTipTemplate}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"> <ToolTip.Triggers> <EventTrigger RoutedEvent="Canvas.Loaded"> <BeginStoryboard> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <System:Boolean>true</System:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </ToolTip.Triggers> </ToolTip> </ToolTipService.ToolTip> <Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent"> <Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z"/> <Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8"/> </Grid> </Border> <Popup x:Name="Popup"> <Grid Opacity="{TemplateBinding Opacity}"> <Border x:Name="PopupBorder" HorizontalAlignment="Stretch" Opacity="0" Background="#11000000" BorderThickness="0"> <Border.RenderTransform> <TranslateTransform X="1" Y="1"/> </Border.RenderTransform> <Border HorizontalAlignment="Stretch" Opacity="1.0" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Padding="0"> <Border.RenderTransform> <TransformGroup> <TranslateTransform X="-1" Y="-1"/> </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> <ListBox x:Name="Selector" Loaded="Selector_Loaded" Background="{TemplateBinding Background}" BorderThickness="0" Foreground="{TemplateBinding Foreground}" ItemTemplate="{TemplateBinding ItemTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemContainerStyle="{TemplateBinding ItemContainerStyle}"/> </Border> </Border> </Grid> </Popup> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Margin="10" > <Grid> <StackPanel> <input:AutoCompleteBox x:Name="acb1" KeyDown="Selector_KeyDown" Style="{StaticResource AutoCompleteBoxStyle1}"/> </StackPanel> </Grid> </Grid>
code
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { List<string> list = new List<string>(); for (int i = 0; i < 100; i++) list.Add("hello" + i); acb1.ItemsSource = list; } private void Button_Click(object sender, RoutedEventArgs e) { } private void Selector_KeyDown(object sender, KeyEventArgs e) { var selecter = _listbox; if (selecter == null) return; if (Keyboard.Modifiers == ModifierKeys.Control) { switch (e.Key) { case Key.Home: selecter.SelectedIndex = 0; break; case Key.End: selecter.SelectedIndex = selecter.Items.Count-1; break; } } } ListBox _listbox; private void Selector_Loaded(object sender, RoutedEventArgs e) { _listbox = sender as ListBox; } }
Please have a try.
Thanks,
08-14-2009 9:47 AM |
Mog,
thank you. I tried to implement page up/down based on this using code below. This works but uses hard-coded page size (30). How to find number
Or any other idea how to implement page up/down keys?
{
}
selecter.SelectedIndex += 30;
selecter.SelectedIndex = selecter.Items.Count-1;
selecter.SelectedIndex -= 30;
selecter.SelectedIndex = 0;
08-15-2009 6:09 AM |
I suppose each item has same height, then we can get display item count by listbox.actualheight/listboxitem.acutalheight. it may be not accurate.
Here is code
private void Selector_KeyDown(object sender, KeyEventArgs e) { var selecter = _listbox; if (selecter == null) return; if (Keyboard.Modifiers == ModifierKeys.Control) { try { // get listbox height var length = _listbox.ActualHeight; // get one item height var itemheight = _listbox.GetContainers().FirstOrDefault().ActualHeight; // calculate visible item count int visiblecount = (int)(length / itemheight); var curindex = _listbox.SelectedIndex; switch (e.Key) { case Key.Home: curindex -= visiblecount; _listbox.SelectedIndex = Math.Max(0, curindex); break; case Key.End: curindex += visiblecount; _listbox.SelectedIndex = Math.Min(_listbox.Items.Count - 1, curindex); break; } } catch { } } }