标准(桌面)窗口组合框有三种风格;简单,下拉列表和删除列表。 Dropdown的工作方式类似于编辑控件和组合框,而Drop List不允许编辑。
我是否遗漏了某些内容,或者Windows 8商店应用中的XAML ComboBox控件是否仅支持Drop List样式?
当我遇到这个问题时,我已经实现了一些东西,而且我看的越多,它似乎就越不受支持。
我是否真的需要使用编辑控件和列表框替换屏幕中的ComboBox?
呸。
答案 0 :(得分:5)
感谢edward.ho.tpe的回答我在TextBox
内使用ComboBoxItem
给自己写了一个小EditableComboBox。
如果要多次使用它,最好创建一个UserControl。
然而,我就这样做了:
<SolidColorBrush x:Key="TransparentBrush" Color="Transparent"/>
<Style x:Key="ComboBoxItemTextBox" TargetType="TextBox">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}"/>
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}"/>
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}"/>
<Setter Property="Background" Value="{StaticResource TransparentBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource TransparentBrush}"/>
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False"/>
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="Margin" Value="-10,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="DeleteButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="GlyphElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="GlyphElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="BorderElement" BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="BackgroundElement" Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}" Margin="{TemplateBinding BorderThickness}">
<TextBlock x:Name="GlyphElement" AutomationProperties.AccessibilityView="Raw" Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}" FontStyle="Normal" FontFamily="{ThemeResource SymbolThemeFontFamily}" HorizontalAlignment="Center" Text="" VerticalAlignment="Center"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="BackgroundElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="BorderElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentElement">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="PlaceholderTextContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Duration="0" To="{ThemeResource TextControlBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
<DoubleAnimation Duration="0" To="{ThemeResource TextControlBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundElement"/>
<DoubleAnimation Duration="0" To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BorderElement"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible"/>
<VisualState x:Name="ButtonCollapsed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="BackgroundElement" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" Margin="{TemplateBinding BorderThickness}" Grid.Row="1" Grid.RowSpan="1"/>
<Border x:Name="BorderElement" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="1"/>
<ContentPresenter x:Name="HeaderContentPresenter" Grid.ColumnSpan="2" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}" FontWeight="Semilight" Margin="0,4,0,4" Grid.Row="0"/>
<ScrollViewer x:Name="ContentElement" AutomationProperties.AccessibilityView="Raw" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsTabStop="False" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="Disabled"/>
<ContentControl x:Name="PlaceholderTextContentPresenter" Grid.ColumnSpan="2" Content="{TemplateBinding PlaceholderText}" Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}" IsHitTestVisible="False" IsTabStop="False" Margin="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Row="1"/>
<Button x:Name="DeleteButton" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" FontSize="{TemplateBinding FontSize}" IsTabStop="False" Grid.Row="1" Style="{StaticResource DeleteButtonStyle}" Visibility="Collapsed" VerticalAlignment="Stretch"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ComboBox SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem IsSelected="True">
<TextBox x:Name="tbComboBox" Style="{StaticResource ComboBoxItemTextBox}" KeyDown="tbComboBox_KeyDown"/>
</ComboBoxItem>
<ComboBoxItem>Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
<ComboBoxItem>Item 3</ComboBoxItem>
<ComboBoxItem>Item 4</ComboBoxItem>
</ComboBox>
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 1 && e.AddedItems[0] != (sender as ComboBox).Items[0])
{
(sender as ComboBox).SelectedIndex = 0;
tbComboBox.Text = (e.AddedItems[0] as ComboBoxItem).Content as String;
}
}
private void tbComboBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Space)
{
if (tbComboBox.SelectionLength > 0)
{
tbComboBox.Text = tbComboBox.Text.Remove(tbComboBox.SelectionStart, tbComboBox.SelectionLength);
tbComboBox.SelectionLength = 0;
}
int pos = tbComboBox.SelectionStart;
tbComboBox.Text = tbComboBox.Text.Insert(pos, " ");
tbComboBox.SelectionStart = pos + 1;
e.Handled = true;
}
}
正如edward.ho.tpe建议TextBox
作为ComboBox
第一项的内容。
TextBox
有一个自定义样式,删除背景,边框,向左移动一点(可选 - 但我喜欢它,因为它提供了更多的空间来写),并更改删除按钮以保持折叠状态。
SelectionChanged
事件处理程序确保TextBox
保持SelectedItem
,并且仅根据所选项目的内容和Text
事件处理程序更改KeyDown
处理空间keydown,否则会触发ComboBox
的下拉列表。
答案 1 :(得分:4)
Syncfusion Controls for WinRT也包含一个ComboBox。但它不是免费的。
答案 2 :(得分:3)
由于WinRT中的组合框项目可以是任何内容,您可以:
<ComboBoxItem>
<TextBox Text="something"/>
</ComboBoxItem>
当用户点击该项目时,他/她可以编辑其内容。
由您决定是否将编辑结果更改为该项目的编辑框,或者只是将新的组合框项目添加到该组合框中。在LostFocus事件中处理此事。
答案 3 :(得分:2)
你没有遗漏任何东西。开箱即用的工具箱中没有可编辑的组合框。
你可能已经尝试过winrt xaml工具包@ http://winrtxamltoolkit.codeplex.com/ 但那也没有。太糟糕了,因为它是免费的。
您可能已经查看过ComponentOne @ http://www.componentone.com/SuperProducts/StudioWinRTXAML/ 但那也没有。
你可能已经看过Infragistics @ http://www.infragistics.com/products/technology-previews/windows8/ 但该工具包仍在“预览”中。
你可能已经看过Telerik @ http://www.telerik.com/products/windows-8/overview.aspx 他们有一个组合框http://www.telerik.com/products/windows-8/controls/combo-box.aspx
但你可能想要一些免费的东西。 目前没有Microsoft XAML Toolkit。 因此,您需要构建自己的或找到一个开源项目。 我此时找不到这样的项目。
但是什么是可编辑的组合框呢?一个标准的组合框和一个文本框,对吧?
答案 4 :(得分:2)
通过设置
combobox.ComboBoxMode = ComboBoxModes.Editable
在syncfusion SfComboBox中,您可以编辑组合框。
此致
Elavarasan M
答案 5 :(得分:1)
尝试名为AutoSuggestBox
的UIControl<AutoSuggestBox PlaceholderText="Company">
<AutoSuggestBox.QueryIcon>
<SymbolIcon Symbol="find"/>
</AutoSuggestBox.QueryIcon>
</AutoSuggestBox>
答案 6 :(得分:1)
我知道这是一个老问题,但是对于像我这样的新搜索者,我发现ComboBox.IsEditable属性很好
答案 7 :(得分:0)
我到处搜索了一个可搜索的组合框,并决定自己编写。它不像您的可编辑组合框,但会在键入时过滤组合框中的选项。也许这可以帮助别人。
您可以像这样定义一个新控件:
<control:SearchableComboBox Margin='5'
x:Name='ComboBoxCountry'
ItemsSourceList='{Binding CountryList}'
ItemsSourceListBase='{Binding CountryListBase}'
PlaceholderText='Select Country'/>
不幸的是,你仍然需要提供一个重复的列表,CountryListBase。如果您有改进建议,请告诉我们!
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace eMoyoConnect.Controls
{
public class SearchableComboBox : ComboBox
{
public ObservableCollection<string> ItemsSourceList
{
get { return (ObservableCollection<string>)GetValue(ItemsSourceListProperty); }
set
{
SetValue(ItemsSourceListProperty, value);
this.ItemsSource = ItemsSourceList;
}
}
public static readonly DependencyProperty ItemsSourceListProperty =
DependencyProperty.Register("ItemsSourceList", typeof(ObservableCollection<string>), typeof(SearchableComboBox),
new PropertyMetadata(null, ItemsSourceListChanged));
private static void ItemsSourceListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var plv = d as SearchableComboBox;
plv.ItemsSource = e.NewValue;
}
public Collection<string> ItemsSourceListBase
{
get { return (Collection<string>)GetValue(ItemsSourceListBaseProperty); }
set
{
SetValue(ItemsSourceListBaseProperty, value);
this.ItemsSource = ItemsSourceListBase;
}
}
public static readonly DependencyProperty ItemsSourceListBaseProperty =
DependencyProperty.Register("ItemsSourceListBase", typeof(Collection<string>), typeof(SearchableComboBox),
new PropertyMetadata(null, ItemsSourceListBaseChanged));
private static void ItemsSourceListBaseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var plv = d as SearchableComboBox;
plv.ItemsSource = e.NewValue;
}
string FilterString = "";
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
if (IsLetterOrSpace(e.Key))
{
if (e.Key == VirtualKey.Space)
FilterString += " ";
else
FilterString += e.Key.ToString();
FilterList(FilterString);
this.ItemsSource = ItemsSourceList;
if (ItemsSourceList.Count > 0)
this.SelectedIndex = 0;
}
else if (e.Key == VirtualKey.Back)
{
if (FilterString.Length > 0)
{
FilterString = FilterString.Substring(0, FilterString.Length - 1);
FilterList(FilterString);
this.ItemsSource = ItemsSourceList;
if (ItemsSourceList.Count > 0)
this.SelectedIndex = 0;
}
}
if (e.Key != VirtualKey.Space)
{
base.OnKeyDown(e);
}
}
protected override void OnGotFocus(RoutedEventArgs e)
{
string selectedValue = "";
if (this.SelectedValue != null)
selectedValue = (string)this.SelectedValue;
FilterString = "";
FilterList(FilterString);
if (!string.IsNullOrEmpty(selectedValue))
this.SelectedValue = selectedValue;
}
internal void FilterList(string FilterString)
{
ItemsSourceList.Clear();
IEnumerable<string> list;
if (!string.IsNullOrEmpty(FilterString))
list = ItemsSourceListBase.Where(x => x.StartsWith(FilterString));
else
list = ItemsSourceListBase;
foreach (var item in list)
ItemsSourceList.Add(item);
}
private bool IsLetterOrSpace(VirtualKey key)
{
return (key == VirtualKey.A
|| key == VirtualKey.B
|| key == VirtualKey.C
|| key == VirtualKey.D
|| key == VirtualKey.E
|| key == VirtualKey.F
|| key == VirtualKey.G
|| key == VirtualKey.H
|| key == VirtualKey.I
|| key == VirtualKey.J
|| key == VirtualKey.K
|| key == VirtualKey.L
|| key == VirtualKey.M
|| key == VirtualKey.N
|| key == VirtualKey.O
|| key == VirtualKey.P
|| key == VirtualKey.Q
|| key == VirtualKey.R
|| key == VirtualKey.S
|| key == VirtualKey.T
|| key == VirtualKey.U
|| key == VirtualKey.V
|| key == VirtualKey.W
|| key == VirtualKey.X
|| key == VirtualKey.Y
|| key == VirtualKey.Z
|| key == VirtualKey.Space);
}
}
}