Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows UWP中的多选下拉列表_Windows_Xaml_Mvvmcross_Uwp Xaml - Fatal编程技术网

Windows UWP中的多选下拉列表

Windows UWP中的多选下拉列表,windows,xaml,mvvmcross,uwp-xaml,Windows,Xaml,Mvvmcross,Uwp Xaml,我想要我的mvvm cross UWP应用程序的多选下拉列表。那么是否有任何预定义的控件?或者我需要实现自定义控件来实现这一点 如有任何帮助或建议,将不胜感激 谢谢UWP中没有内置的多选组合框,但您可以像这样构建自己的组合框- 基本上,您可以将复选框添加到组合框中的每个项目,并创建一个逻辑来收集所选项目,并提供一种可绑定的方式来访问它们 为了使它更简单,您可以创建一个特殊类,该类将有一个IsChecked属性,只需将带有双向绑定的复选框添加到此属性即可。这将确保UI中的复选框将反映在类中,然后您

我想要我的mvvm cross UWP应用程序的多选下拉列表。那么是否有任何预定义的控件?或者我需要实现自定义控件来实现这一点

如有任何帮助或建议,将不胜感激


谢谢

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="&#xE0E5;" 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>