Windows UWP中的多选下拉列表
我想要我的mvvm cross UWP应用程序的多选下拉列表。那么是否有任何预定义的控件?或者我需要实现自定义控件来实现这一点 如有任何帮助或建议,将不胜感激Windows UWP中的多选下拉列表,windows,xaml,mvvmcross,uwp-xaml,Windows,Xaml,Mvvmcross,Uwp Xaml,我想要我的mvvm cross UWP应用程序的多选下拉列表。那么是否有任何预定义的控件?或者我需要实现自定义控件来实现这一点 如有任何帮助或建议,将不胜感激 谢谢UWP中没有内置的多选组合框,但您可以像这样构建自己的组合框- 基本上,您可以将复选框添加到组合框中的每个项目,并创建一个逻辑来收集所选项目,并提供一种可绑定的方式来访问它们 为了使它更简单,您可以创建一个特殊类,该类将有一个IsChecked属性,只需将带有双向绑定的复选框添加到此属性即可。这将确保UI中的复选框将反映在类中,然后您
谢谢UWP中没有内置的多选组合框,但您可以像这样构建自己的组合框- 基本上,您可以将复选框添加到组合框中的每个项目,并创建一个逻辑来收集所选项目,并提供一种可绑定的方式来访问它们
为了使它更简单,您可以创建一个特殊类,该类将有一个
IsChecked
属性,只需将带有双向绑定的复选框添加到此属性即可。这将确保UI中的复选框将反映在类中,然后您可以枚举所有项,以查找那些已选中IsChecked
设置为true
的项。我将这样构建它
首先建立你的班级
public class MultiSelectComboBox : ComboBox
{
public List<ComboBoxItem> SelectedItems
{
get { return (List<ComboBoxItem>)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(List<ComboBoxItem>), typeof(MultiSelectComboBox), new PropertyMetadata(new List<ComboBoxItem>()));
public static void SetIsSelected(UIElement element, bool value)
{
element.SetValue(IsSelectedProperty, value);
}
public static bool GetIsSelected(UIElement element)
{
return (bool)element.GetValue(IsSelectedProperty);
}
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.RegisterAttached("IsSelected", typeof(bool), typeof(ComboBoxItem), new PropertyMetadata(false, OnIsSelectedChanged));
public static void SetParentComboBox(UIElement element, MultiSelectComboBox value)
{
element.SetValue(ParentComboBoxProperty, value);
}
public static MultiSelectComboBox GetParentComboBox(UIElement element)
{
return (MultiSelectComboBox)element.GetValue(ParentComboBoxProperty);
}
public static readonly DependencyProperty ParentComboBoxProperty =
DependencyProperty.RegisterAttached("ParentComboBox", typeof(MultiSelectComboBox), typeof(MultiSelectComboBox), new PropertyMetadata(null));
protected override DependencyObject GetContainerForItemOverride()
{
ComboBoxItem comboBoxitem = new ComboBoxItem();
MultiSelectComboBox.SetParentComboBox(comboBoxitem, this);
return comboBoxitem;
}
private static void OnIsSelectedChanged(object comboBoxItem, DependencyPropertyChangedEventArgs args)
{
ComboBoxItem item = comboBoxItem as ComboBoxItem;
if (item != null)
{
MultiSelectComboBox parent = MultiSelectComboBox.GetParentComboBox(item);
if (MultiSelectComboBox.GetIsSelected(item))
{
parent.SelectedItems.Add(item);
}
else
{
parent.SelectedItems.Remove(item);
}
}
}
}
公共类多选组合框:组合框
{
公共列表SelectedItems
{
获取{return(List)GetValue(SelectedItemsProperty);}
set{SetValue(selecteditemsprroperty,value);}
}
公共静态只读从属属性SelectedItemsProperty=
Register(“SelectedItems”、typeof(List)、typeof(MultiSelectComboBox)、newpropertyMetadata(new List());
公共静态无效集合已选择(UIElement元素,布尔值)
{
元素.SetValue(IsSelectedProperty,value);
}
公共静态bool GetIsSelected(UIElement)
{
返回(bool)元素.GetValue(IsSelectedProperty);
}
公共静态只读从属属性IsSelectedProperty=
DependencyProperty.RegisterAttached(“IsSelected”、typeof(bool)、typeof(ComboBoxItem)、new PropertyMetadata(false、OnSelectedChanged));
公共静态void SetParentComboBox(UIElement元素,MultiSelectComboBox值)
{
SetValue(ParentComboBoxProperty,value);
}
公共静态MultiSelectComboBox GetParentComboBox(UIElement元素)
{
return(MultiSelectComboBox)元素.GetValue(ParentComboBoxProperty);
}
公共静态只读DependencyProperty ParentComboxProperty=
DependencyProperty.RegisterAttached(“ParentComboBox”、typeof(MultiSelectComboBox)、typeof(MultiSelectComboBox)、new PropertyMetadata(null));
受保护的覆盖依赖对象GetContainerForItemOverride()
{
ComboBoxItem ComboBoxItem=新ComboBoxItem();
SetParentComboBox(comboBoxitem,this);
返回组合框项目;
}
SelectedChanged上的私有静态void(对象comboBoxItem,DependencyPropertyChangedEventArgs参数)
{
ComboBoxItem=ComboBoxItem作为ComboBoxItem;
如果(项!=null)
{
MultiSelectComboBox父项=MultiSelectComboBox.GetParentComboBox(项);
if(MultiSelectComboBox.GetIsSelected(项目))
{
父项。选择编辑项。添加(项);
}
其他的
{
父项。选择编辑项。删除(项);
}
}
}
}
然后创建您的项目模板
<local:MultiSelectComboBox ItemsSource="{Binding Items}" SelectedItems="{Binding SelectedItems, Mode=TwoWay}">
<local:MultiSelectComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding ItemContent}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ComboBoxItem}, Path=IsSelected, Mode=TwoWay}"/>
</DataTemplate>
</local:MultiSelectComboBox.ItemTemplate>
</local:MultiSelectComboBox>
然而,这可能需要一些按摩才能开始工作。最后,您希望对Combobox进行子类化,并使其执行一些新功能 令人惊讶的是,内置的UWP ComboBox仍然不支持这种常见场景,而且我在任何地方都找不到任何有效的解决方案 这是我的最小解决方案,以防其他人看到 XAML:
C#:
使用System.Linq;
使用System.Runtime.InteropServices.WindowsRuntime;
使用Windows基金会;
使用Windows。
使用Windows.UI.Xaml;
使用Windows.UI.Xaml.Controls;
使用Windows.UI.Xaml.Controls.Primitives;
使用Windows.UI.Xaml.Data;
使用Windows.UI.Xaml.Input;
使用Windows.UI.Xaml.Media;
使用Windows.UI.Xaml.Navigation;
命名空间MonoTorrent.GUI.Controls
{
公共密封部分类MultiSelectComboBox:UserControl
{
#区域项资源依赖项属性
公共对象项资源
{
获取{返回GetValue(ItemsSourceProperty);}
设置
{
设置值(ItemsSourceProperty,value);
listView.ItemsSource=值;
}
}
公共静态只读依赖项Property ItemsSourceProperty=
DependencyProperty.Register(“ItemsSource”、typeof(object)、typeof(MultiSelectComboBox)、new PropertyMetadata(new List()、OnItemsSourcePropertyChanged));
私有静态void OnItemSourcePropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
MultiSelectComboBox实例=d作为MultiSelectComboBox;
if(实例!=null&&e.NewValue!=null)
{
instance.listView.ItemsSource=e.NewValue;
}
}
#端区
#区域ItemTemplate依赖项属性
公共数据模板ItemTemplate
{
获取{return(DataTemplate)GetValue(ItemTemplateProperty);}
设置
{
SetValue(ItemTemplateProperty,值);
listView.ItemTemplate=值;
}
}
公共静态只读DependencyProperty ItemTemplateProperty=
DependencyProperty.Register(“ItemTemplate”、typeof(DataTemplate)、typeof(MultiSelectComboBox)、new PropertyMetadata(null,OnItemTemplatePropertyChanged));
私有静态void OnItemTemplatePropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
<UserControl
x:Class="MonoTorrent.GUI.Controls.MultiSelectComboBox"
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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<StackPanel x:Name="rootElement" Orientation="Vertical" Margin="0">
<Button x:Name="comboBoxButton" BorderBrush="Gray" BorderThickness="2" Background="Transparent"
VerticalAlignment="Top" Click="ComboBoxButton_Click"
HorizontalAlignment="Stretch" FontSize="14" MinHeight="26" Height="26" Padding="0"
Width="{Binding ElementName=rootElement, Path=ActualWidth}">
<Grid VerticalAlignment="Stretch" Width="{Binding ElementName=rootElement, Path=ActualWidth}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="32" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="SelectedValueTextBlock"
Grid.Column="0" VerticalAlignment="Center" FontSize="15" HorizontalAlignment="Left" Padding="7,0,0,0" />
<FontIcon Grid.Column="1" FontSize="12" FontFamily="Segoe MDL2 Assets" Glyph="" HorizontalAlignment="Right"
Margin="0,5,10,5" VerticalAlignment="Center" />
</Grid>
</Button>
<Popup x:Name="comboBoxPopup" IsLightDismissEnabled="True">
<Border BorderBrush="{ThemeResource ComboBoxDropDownBorderBrush}"
BorderThickness="{ThemeResource ComboBoxDropdownBorderThickness}"
Background="{ThemeResource ComboBoxDropDownBackground}"
HorizontalAlignment="Stretch">
<ListView x:Name="listView"
SelectionMode="Multiple"
SingleSelectionFollowsFocus="False"
SelectionChanged="ListView_SelectionChanged">
</ListView>
</Border>
</Popup>
</StackPanel>
</UserControl>
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace MonoTorrent.GUI.Controls
{
public sealed partial class MultiSelectComboBox : UserControl
{
#region ItemsSource dependency property
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set
{
SetValue(ItemsSourceProperty, value);
listView.ItemsSource = value;
}
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(object), typeof(MultiSelectComboBox), new PropertyMetadata(new List<object>(), OnItemsSourcePropertyChanged));
private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MultiSelectComboBox instance = d as MultiSelectComboBox;
if (instance != null && e.NewValue != null)
{
instance.listView.ItemsSource = e.NewValue;
}
}
#endregion
#region ItemTemplate dependency property
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set
{
SetValue(ItemTemplateProperty, value);
listView.ItemTemplate = value;
}
}
public static readonly DependencyProperty ItemTemplateProperty =
DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(MultiSelectComboBox), new PropertyMetadata(null, OnItemTemplatePropertyChanged));
private static void OnItemTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MultiSelectComboBox instance = d as MultiSelectComboBox;
if (instance != null && e.NewValue as DataTemplate != null)
{
instance.listView.ItemTemplate = (DataTemplate)e.NewValue;
}
}
#endregion
#region SelectedItems dependency property
public IList<object> SelectedItems
{
get { return (IList<object>)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(IList<object>), typeof(MultiSelectComboBox), new PropertyMetadata(new List<object>()));
#endregion
#region PopupHeight dependency property
public double PopupHeight
{
get { return (double)GetValue(PopupHeightProperty); }
set
{
SetValue(PopupHeightProperty, value);
if (value != 0)
{
listView.Height = value;
}
}
}
public static readonly DependencyProperty PopupHeightProperty =
DependencyProperty.Register("PopupHeight", typeof(double), typeof(MultiSelectComboBox), new PropertyMetadata(0.0, OnPopupHeightPropertyChanged));
private static void OnPopupHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MultiSelectComboBox instance = d as MultiSelectComboBox;
if (instance != null && (double)e.NewValue != 0)
{
instance.listView.Height = (double)e.NewValue;
}
}
#endregion
#region PopupWidth dependency property
public double PopupWidth
{
get { return (double)GetValue(PopupWidthProperty); }
set
{
SetValue(PopupWidthProperty, value);
if (value != 0)
{
listView.Width = value;
}
}
}
public static readonly DependencyProperty PopupWidthProperty =
DependencyProperty.Register("PopupWidth", typeof(double), typeof(MultiSelectComboBox), new PropertyMetadata(0.0, OnPopupWidthPropertyChanged));
private static void OnPopupWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MultiSelectComboBox instance = d as MultiSelectComboBox;
if (instance != null && (double)e.NewValue != 0)
{
instance.listView.Width = (double)e.NewValue;
}
}
#endregion
#region NoSelectionText dependency property
public string NoSelectionText
{
get { return (string)GetValue(NoSelectionTextProperty); }
set { SetValue(NoSelectionTextProperty, value); }
}
public static readonly DependencyProperty NoSelectionTextProperty =
DependencyProperty.Register("NoSelectionText", typeof(string), typeof(MultiSelectComboBox), new PropertyMetadata("No selection"));
#endregion
#region MultipleSelectionTextFormat dependency property
public string MultipleSelectionTextFormat
{
get { return (string)GetValue(MultipleSelectionTextFormatProperty); }
set { SetValue(MultipleSelectionTextFormatProperty, value); }
}
public static readonly DependencyProperty MultipleSelectionTextFormatProperty =
DependencyProperty.Register("MultipleSelectionTextFormat", typeof(string), typeof(MultiSelectComboBox), new PropertyMetadata("{0} selected"));
#endregion
public MultiSelectComboBox()
{
this.InitializeComponent();
this.Loaded += MultiSelectComboBox_Loaded;
}
private void MultiSelectComboBox_Loaded(object sender, RoutedEventArgs e)
{
this.UpdateSelectionText();
}
private void ComboBoxButton_Click(object sender, RoutedEventArgs e)
{
listView.SelectedItems.Clear();
foreach (var item in SelectedItems)
{
listView.SelectedItems.Add(item);
}
this.comboBoxPopup.IsOpen = true;
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!comboBoxPopup.IsOpen)
{
return;
}
this.SelectedItems = listView.SelectedItems.ToList();
UpdateSelectionText();
}
private void UpdateSelectionText()
{
if (this.SelectedItems == null || this.SelectedItems.Count == 0)
{
this.SelectedValueTextBlock.Text = NoSelectionText;
}
else if (this.SelectedItems.Count == 1)
{
this.SelectedValueTextBlock.Text = this.SelectedItems.First().ToString();
}
else
{
this.SelectedValueTextBlock.Text = String.Format(MultipleSelectionTextFormat, this.SelectedItems.Count);
}
}
}
}
<controls:MultiSelectComboBox x:Name="MultiSelectComboBox"
ItemsSource="{Binding Values}"
SelectedItems="{Binding SelectedValues, Mode=TwoWay}"
NoSelectionText="{Binding EmptySelectionString}"
MultipleSelectionTextFormat="{Binding MultipleSelectedFormatString}"
PopupHeight="500" PopupWidth="200"
HorizontalAlignment="Stretch" FontSize="14" MinHeight="26" Height="26">
<controls:MultiSelectComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</controls:MultiSelectComboBox.ItemTemplate>
</controls:MultiSelectComboBox>