Code Monkey home page Code Monkey logo

multiselect-combobox's Introduction

Sdl.MultiSelectComboBox (WPF Custom Control)

NuGet Stats

Overview

The multi selection combo box is a WPF custom control with multiple item selection capabilities, along with customizable features to group, sort and filter items in the collection.

Usage Demonstration Gif

Components and Features

Components Image

Selected Items Panel

The selected items are displayed like tags with a remove button They can be added or removed from the selected items collection, by selecting them from the items present in the Dropdown Menu list. Additionally, items can also be removed by interacting with them directly from the Selected Items Panel, as follows:

Device Action Description
Keyboard Backspace or Delete key If the Filter Criteria is empty, then the last item in the selected items collection is removed.
Mouse Remove Item Button The item is removed from the selected items collection

Visual States

The control has two visual states, Readonly and EditMode, which is identified by the IsEditMode property. When the control is in readonly mode, the items cannot be edited from the view. To switch to edit mode, select the control in the view or hit (F2) when the control has focus. Once the control is in edit mode, the items can be filtered, selected or removed. To switch back to readonly, move focus away from the control by selecting any other control in the view or by deactivating the parent window.

Visual state Description Example
Readonly The Dropdown Menu is collapsed and items present in the Selected Items Panel cannot be edited. Readonly Image
EditMode The Dropdown Menu can be expanded or collapsed when the button is clicked and items present in the Selected Items Panel can be edited. EditMode Image

Filter Criteria

When you type a character in the text area, the control applies a filter on the collection and suggests a list of items matching that criteria in the Dropdown Menu list. The developer can override the default filter service, based on their own business logic requirements, that implements IFilterService.

Filter Criteria Image

Depending on whether or not the ClearFilterOnDropdownClosing property is set to true and Dropdown Menu list as keyboard focus, the Filter Criteria is cleared automatically as the Dropdown Menu is closing.

Keyboard focus Action
True The Filter Criteria is cleared as the Dropdown Menu is closing.
False No attempt is made to change the current filter.

Dropdown Menu

Presents a list of suggestions that can be selected by the user. If no Filter Criteria is applied, then all items in the collection are displayed

Visibility

The Dropdown Menu can be expanded only when the control is in EditMode.

Visibility Actions
Expand
  • Left mouse click anywhere within the control area, with exception to the Remove Item Button of the item.
  • Down arrow key on the keyboard when the control has focus.
  • Change the *Filter Criteria*, by typing characters in the text area.
Collapse
  • Left mouse click anywhere within the control area, with exception to the Remove Item Button of the item.
  • Return key.
    • The item that has focus in the list is selected
    • The *Filter Criteria* is removed
  • Esc key
  • Move focus away from the control by selecting any other control in the view or by deactivating the parent window.

Item Group

The items in the collection can be grouped by implementing IItemGroupAware. In addition to the header name, this interface exposes a property to manage the order in which the group headers are displayed. Item Group Image

Item Sorting

The sort order is based on the order of the items in the collection that was received when the ItemsSource is set.

Item Selection

Items can be added or removed from the selected items collection, by selecting them from the items present in the Dropdown Menu list.

Device Actions Description
Mouse Left mouse click The item that has selection focus in the list is selected/unselected.
Mouse Shift + Left mouse click All items between the previous and current item that has focus are selected.
Keyboard Return key - The item that has focus in the list is selected.
- The Filter Criteria is removed.
- The Dropdown Menu is closed
Keyboard Space key The item that has focus in the list is selected/unselected.
Keyboard Shift + Up or Down key The item that has focus in the list is selected/unselected.

Disabled Item

Implement IItemEnabledAware to identify whether or not the items are enabled. When an item is not enabled, then it will not be selectable from the Dropdown Menu list and removed from the Selected Items Panel automatically.

Selected Item

Items in the Dropdown Menu list can be selected/unselected via the Mouse or Keyboard. When the item is selected, the style is updated to reflect a selected state.

Example Project

The example project demonstrates how to implement the Sdl.MultiSelectComboBox custom control to your project, and provides good examples in understanding the controls behaviours. Example Project Image

Examples

The following example creates an Sdl.MultiSelectComboBox. The example populates the control by binding the ItemsSource property to a collection of type object, that implements IItemEnabledAware and IItemGroupAware. The example also binds the SelectedItemsChangedBehaviour to a command to receive a notification of SelectedItemsChangedEventArgs whenever the selected items collection changes and then display those results in a TextBlock on the view. Additionally, both the selected and dropdown list item templates are customized to display an image along with the item name.

Example.xaml

<Window x:Class="MultiSelectComboBoxExample.Example"
        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:sdl="http://schemas.sdl.com/xaml"
        xmlns:models="clr-namespace:MultiSelectComboBoxExample.Models"
        d:DataContext="{d:DesignInstance {x:Type models:LanguageItems}}"
        mc:Ignorable="d"
        Title="Example" Height="250" Width="400">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/MultiSelectComboBox.Resources.xaml"/>              
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Vertical">
            <sdl:MultiSelectComboBox Height="100"
                ItemsSource="{Binding Items}"
                IsEditable="true"
                SelectionMode="Multiple"
                SelectedItemTemplate="{StaticResource MultiSelectComboBox.SelectedItems.ItemTemplate}"
                DropdownItemTemplate="{StaticResource MultiSelectComboBox.Dropdown.ListBox.ItemTemplate}"
                sdl:SelectedItemsChangedBehaviour.SelectedItemsChanged="{Binding SelectedItemsChangedCommand}"/>
            <TextBlock Text="{Binding Path=EventLog}" Height="100"/>
        </StackPanel>
    </Grid>
</Window>

DataTemplate: MultiSelectComboBox.Dropdown.ListBox.ItemTemplate

<DataTemplate x:Key="MultiSelectComboBox.Dropdown.ListBox.ItemTemplate" DataType="models:LanguageItem">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="30"/>
        </Grid.ColumnDefinitions>
 
        <Image Grid.Column="0" Style="{StaticResource MultiSelectComboBox.Image.Style}"/>
        <TextBlock Grid.Column="1" Text="{Binding Path=Name}" Style="{StaticResource MultiSelectComboBox.DefaultTextBlock.Style}"/>
        <TextBlock Grid.Column="2" Text="{Binding Path=SelectedOrder}" Margin="5,0"
                Foreground="{StaticResource MultiSelectComboBox.DropDown.ListBoxItem.SelectedOrder.Foreground}"
                VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=SelectedOrder}" Value="-1">
                            <Setter Property="Visibility" Value="Hidden" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</DataTemplate>

DataTemplate: MultiSelectComboBox.SelectedItems.ItemTemplate

<DataTemplate x:Key="MultiSelectComboBox.SelectedItems.ItemTemplate" DataType="models:LanguageItem">
    <StackPanel Orientation="Horizontal" Margin="0,-4">
        <Image Style="{StaticResource MultiSelectComboBox.Image.Style}" Margin="2,0,4,-1"/>
        <TextBlock Text="{Binding Path=Name}" Style="{DynamicResource MultiSelectComboBox.DefaultTextBlock.Style}" Margin="2,0" />
    </StackPanel>
</DataTemplate>

Style: MultiSelectComboBox.Image.Style

<Style x:Key="MultiSelectComboBox.Image.Style" TargetType="Image">
    <Setter Property="Stretch" Value="Fill"/>
    <Setter Property="Source" Value="{Binding Path=Image}"/>
    <Setter Property="RenderOptions.BitmapScalingMode" Value="NearestNeighbor"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="RenderOptions.EdgeMode" Value="Aliased"/>
    <Setter Property="Margin" Value="0,0,4,0"/>
    <Setter Property="Width" Value="{Binding Path=ImageSize.Width}"/>
    <Setter Property="Height" Value="{Binding Path=ImageSize.Height}"/>
</Style>

Style: MultiSelectComboBox.DefaultTextBlock.Style

<Style x:Key="MultiSelectComboBox.DefaultTextBlock.Style" TargetType="TextBlock">
    <Setter Property="FontFamily" Value="{StaticResource MultiSelectComboBox.Text.FontFamily}"/>
    <Setter Property="FontSize" Value="11"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="Control.VerticalContentAlignment" Value="Center"/>
    <Setter Property="TextWrapping" Value="NoWrap"/>
    <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Margin" Value="1"/>
    <Setter Property="Foreground" Value="{StaticResource MultiSelectComboBox.Text.Foreground}"/>
    <Setter Property="TextAlignment" Value="Left"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}}" Value="False">
            <Setter Property="Foreground" Value="{StaticResource MultiSelectComboBox.Text.Disabled.Foreground}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

The following example defines the data context (i.e. models:LanguageItems) that the Sdl.MultiSelectComboBox binds to from the previous example.

LanguageItems : INotifyPropertyChanged

public class LanguageItems : INotifyPropertyChanged
{
    private List<LanguageItem> _items;   
 
    public LanguageItems()
    {
        SelectedItemsChangedCommand = new SelectedItemsChangedCommand(UpdateEventLog, UpdateSelectedItems);
 
        var group = new LanguageItemGroup(0, "All Items");
        Items = new List<LanguageItem>
        {
            new LanguageItem
            {
                Id = "en-US",
                Name= "English (United States)",
                Group = group
            },
            new LanguageItem
            {
                Id = "it-IT",
                Name= "Italian (Italy)",
                Group = group
            },
            new LanguageItem
            {
                Id = "de-DE",
                Name= "German (Germany)",
                Group = group
            }
        };
    }
     
    public ICommand SelectedItemsChangedCommand { get; }
 
    public List<LanguageItem> Items
    {
        get => _items ?? (_items = new List<LanguageItem>());
        set => _items = value;
    }
 
    public string EventLog { get; set; }
 
    private void UpdateEventLog(string action, string text)
    {
        EventLog += action + " => " + text + "\r\n";
        OnPropertyChanged(nameof(EventLog));
    }
 
    private void UpdateSelectedItemsCount(int count)
    {
        SelectedItemsCount = count;
        OnPropertyChanged(nameof(SelectedItemsCount));
    }
 
    private void UpdateSelectedItems(ICollection selected)
    {           
        foreach (var item in _items)
        {
            var selectedItemIndex = selected.Cast<LanguageItem>().ToList().IndexOf(item);
            item.SelectedOrder = selectedItemIndex > -1 ? selectedItemIndex + 1 : -1;
        }
 
        UpdateSelectedItemsCount(selected.Count);
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }       
 }

LanguageItem : IItemEnabledAware, IItemGroupAware, INotifyPropertyChanged

public class LanguageItem : IItemEnabledAware, IItemGroupAware, INotifyPropertyChanged
{
    private string _id;
    private string _name;
    private bool _isEnabled;
    private int _selectedOrder;
    private IItemGroup _group;
    private BitmapImage _image;
    private Size _imageSize;
 
    public LanguageItem()
    {
        _isEnabled = true;
        _selectedOrder = -1;
    }
 
    /// <summary>
    /// Unique id in the collection
    /// </summary>
    public string Id
    {
        get => _id;
        set
        {
            if (_id != null && string.Compare(_id, value, StringComparison.InvariantCulture) == 0)
            {
                return;
            }
 
            _id = value;
            OnPropertyChanged(nameof(Id));
        }
    }
 
    /// <summary>
    /// The item name.
    ///
    /// The filter criteria is applied on this property when using the default filter service.
    /// </summary>
    public string Name
    {
        get => _name;
        set
        {
            if (_name != null && string.Compare(_name, value, StringComparison.InvariantCulture) == 0)
            {
                return;
            }
 
            _name = value;
            OnPropertyChanged(nameof(Name));
        }
    }
 
    /// <summary>
    /// Identifies whether the item is enabled or not.
    ///
    /// When the item is not enabled, then it will not be selectable from the dropdown list and removed
    /// from the selected items automatically.
    /// </summary>
    public bool IsEnabled
    {
        get => _isEnabled;
        set
        {
            if (_isEnabled.Equals(value))
            {
                return;
            }
 
            _isEnabled = value;
            OnPropertyChanged(nameof(IsEnabled));
        }
    }
 
    /// <summary>
    /// The order in which the items are added to the selected collection. 
    /// 
    /// This order is independent to the group and sort order of the items in the collection. This selected
    /// order is visible in each of the selected items from the dropdown list and visually represented by
    /// the order of the items in the Selected Items Panel.
    /// </summary>
    public int SelectedOrder
    {
        get => _selectedOrder;
        set
        {
            if (_selectedOrder.Equals(value))
            {
                return;
            }
 
            _selectedOrder = value;
            OnPropertyChanged(nameof(SelectedOrder));
        }
    }
 
    /// <summary>
    /// Identifies the name and order of the group header
    /// </summary>
    public IItemGroup Group
    {
        get => _group;
        set
        {
            if (_group != null && _group.Equals(value))
            {
                return;
            }
 
            _group = value;
            OnPropertyChanged(nameof(Group));
        }
    }
 
    /// <summary>
    /// The item Image.
    ///
    /// Use the ImageSize to identify the space required to display the image in the view.
    /// </summary>
    public BitmapImage Image
    {
        get => _image;
        set
        {
            _image = value;
            OnPropertyChanged(nameof(Image));
        }
    }
 
    /// <summary>
    /// The image size.
    ///
    /// Measures the width and height that is required to display the image.
    /// </summary>
    public Size ImageSize
    {
        get => _imageSize;
        set
        {
            if (_imageSize.Equals(value))
            {
                return;
            }
 
            _imageSize = value;
            OnPropertyChanged(nameof(ImageSize));
        }
    }
 
    public CultureInfo CultureInfo { get; set; }
 
    public override string ToString()
    {
        return Name;
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

SelectedItemsChangedCommand : ICommand

public class SelectedItemsChangedCommand : ICommand
{
    private readonly Action<string, string> _updateEventLog;
    private readonly Action<ICollection> _updateSelectedItems;
 
    public SelectedItemsChangedCommand(Action<string, string> updateEventLog, Action<ICollection>)
    {
        _updateEventLog = updateEventLog;
        _updateSelectedItems = updateSelectedItems;
    }
 
    public bool CanExecute(object parameter)
    {
        return parameter is SelectedItemsChangedEventArgs && _updateEventLog != null;
    }
 
    public void Execute(object parameter)
    {
        if (parameter is SelectedItemsChangedEventArgs args)
        {
            _updateSelectedItems?.Invoke(args.Selected);
 
            var addedItems = GetAggregatedText(args.Added);
            var removedItems = GetAggregatedText(args.Removed);
            var selectedItems = GetAggregatedText(args.Selected);
 
            var report = "Added - " + args.Added?.Count + (!string.IsNullOrEmpty(addedItems) ? " (" + TrimToLength(addedItems, 100) + ") " : string.Empty)
				+ ", Removed - " + args.Removed?.Count + (!string.IsNullOrEmpty(removedItems) ? " (" + TrimToLength(removedItems, 100) + ") " : string.Empty)
				+ ", Selected - " + args.Selected?.Count + (!string.IsNullOrEmpty(selectedItems) ? " (" + TrimToLength(selectedItems, 100) + ") " : string.Empty);

			_updateEventLog?.Invoke("Selected Changed", report);
        }
    }
         
    public event EventHandler CanExecuteChanged;
 
    private string TrimToLength(string text, int length)
    {
        if (text?.Length > length)
        {
            text = text.Substring(0, length) + "...";
        }
 
        return text;
    }
 
    private static string GetAggregatedText(ICollection items)
    {
        var itemsText = string.Empty;
        return items?.Cast<LanguageItem>().Aggregate(itemsText, (current, item) => current + ((!string.IsNullOrEmpty(current) ? ", " : string.Empty) + item.Id));
    }
 }

LanguageItemGroup : IItemGroup

public class LanguageItemGroup : IItemGroup
{
    public int Order { get; set; }
    public string Name { get; }
 
    public LanguageItemGroup(int index, string name)
    {
        Order = index;
        Name = name;
    }
 
    public override string ToString()
    {
        return Name;
    }
}

Remarks

The Sdl.MultiSelectComboBox allows the user to select an item from a Dropdown Menu list and optionally apply a filter on the list by typing text in the text box of the Selected Items Panel. The SelectionMode and IsEditable properties specify how the Item Selection behaves, especially when the user is interacting with items from the Selected Items Panel, as follows:

SelectionMode.Multiple (default) SelectionMode.Single
IsEditable is true (default) Multiple items can be selected/unselected from the Dropdown Menu list

The Remove Item Button is displayed in each of the selected items in the Selected Items Panel.

Items in the Selected Items Panel can be removed when the user hits the Delete or Back key
A single item can be selected from the Dropdown Menu list. When a new item is selected, it substitutes the previously selected item in the Selected Items Panel.

The Remove Item Button is displayed in each of the selected items in the Selected Items Panel.

Items in the Selected Items Panel can be removed when the user hits the Delete or Back key
IsEditable is false Multiple items can be selected/unselected from the Dropdown Menu list.

The Remove Item Button is not displayed in each of the selected items in the Selected Items Panel.

Items in the Selected Items Panel cannot be removed when the user hits the Delete or Back key
A single item can be selected from the Dropdown Menu list. When a new item is selected, it substitutes the previously selected item in the Selected Items Panel.

The Remove Item Button is not displayed in each of the selected items in the Selected Items Panel.

Items in the Selected Items Panel cannot be removed when the user hits the Delete or Back key

Customizing the Style and template

You can modify the default Style and ControlTemplate to give the control a unique appearance. For information about modifying a controls style and template, see Customizing the Appearance of an Existing Control by Creating a ControlTemplate and Styling controls. The default style, template, and resources that define the look of the control are included in the generic.xaml file.

This table shows the resources used by the Sdl.MultiSelectComboBox control.

Resource key Description
MultiSelectComboBox.DropDown.Button.Background Drop down button background color at rest
MultiSelectComboBox.DropDown.Button.Border Drop down button border brush at rest
MultiSelectComboBox.DropDown.Button.Disabled.Background Drop down button background color when disabled
MultiSelectComboBox.DropDown.Button.Disabled.Border Drop down button border brush when disabled
MultiSelectComboBox.DropDown.Button.Disabled.Foreground Drop down button foreground color when disabled
MultiSelectComboBox.DropDown.Button.MouseOver.Background Drop down button background color when the mouse is hovering
MultiSelectComboBox.DropDown.Button.MouseOver.Border Drop down button border brush when the mouse is hovering
MultiSelectComboBox.DropDown.Button.Pressed.Background Drop down button background color when the button is pressed
MultiSelectComboBox.DropDown.Button.Pressed.Border Drop down button border brush when the button is pressed
MultiSelectComboBox.DropDown.ListBox.GroupHeader.Background Drop down list group header background color
MultiSelectComboBox.DropDown.ListBox.GroupHeader.Foreground Drop down list group header foreground color
MultiSelectComboBox.DropDown.ListBoxItem.Selector.Background Drop down list item background color of the item when it has selection focus
MultiSelectComboBox.DropDown.ListBoxItem.Selector.Border Drop down list item border brush of the item when it has selection focus
MultiSelectComboBox.DropDown.ListBoxItem.Selected.Background Drop down list item background color of the item when it is selected
MultiSelectComboBox.DropDown.ListBoxItem.Selected.Border Drop down list item border brush of the item when it is selected
MultiSelectComboBox.SelectedItem.Border Selected item border brush that surrounds the selected item in the Selected Items Panel
MultiSelectComboBox.SelectedItem.Button.Foreground Selected Item button foreground color
MultiSelectComboBox.SelectedItem.Button.Hover.Background Selected Item button foreground when the mouse if hovering over it
MultiSelectComboBox.SelectedItem.Button.Light.Foreground Selected Item button light foreground color
MultiSelectComboBox.SelectedItemsPanel.Border Selected Items Panel border brush
MultiSelectComboBox.Text.Disabled.Foreground Default text foreground color when disabled
MultiSelectComboBox.Text.FontFamily Default FontFamily for all text in the control
MultiSelectComboBox.Text.Foreground Default text foreground color

The sample project includes an example of a customized version of control template style for the Sdl.MultiSelectComboBox control, where the item selection styles are modified and a popup control is displayed with the CultureInfo properties when hovering over the language items in the Selected Items Panel. Make reference to the following. Custom Control Template image

API

interface IFilterService

/// <summary>
/// The filter service that is used to apply a custom filter on the items that are displayed
/// from the collection.
/// </summary>
public interface IFilterService
{
    /// <summary>
    /// The filter criteria should be set before applying the Filter
    /// </summary>
    /// <param name="criteria">The filter criteria that is applied</param>
    void SetFilter(string criteria);

    /// <summary>
    /// Gets or sets a callback used to determine if an item is suitable for inclusion in the view.
    /// </summary>
    Predicate<object> Filter { get; set; }
}

interface IItemEnabledAware

/// <summary>
/// IEnabledAware - Identifies whether the item is enabled or not.
/// </summary>
public interface IItemEnabledAware
{
    /// <summary>
    /// Identifies whether the item is enabled or not.
    /// 
    /// When the item is not enabled, then it will not be selectable from the dropdown list and removed
    /// from the selected items automatically.
    /// </summary>
    bool IsEnabled { get; set; }
}

interface IItemGroup

/// <summary>
/// Identifies the name and order of the group header
/// </summary>
public interface IItemGroup
{
    /// <summary>
    /// The group name.
    /// </summary>
    string Name { get; }

    /// <summary>
    /// The display order of the group headers.
    /// </summary>
    int Order { get; set; }
}

interface IItemGroupAware

/// <summary>
/// IGroupAware - provides support for grouping the items
/// </summary>
public interface IItemGroupAware
{
    /// <summary>
    /// Used to identify the name and order of the group header
    /// </summary>
    IItemGroup Group { get; set; }
}

EventArgs

FilterTextChangedEventArgs : RoutedEventArgs

/// <summary>
/// Raised when the filter criteria has changed
/// </summary>
public class FilterTextChangedEventArgs : RoutedEventArgs
{    
    /// <summary>
    /// The filter critera applied on the collection of items
    /// </summary>
    public string Text { get; }

    /// <summary>
    /// The filtered list of items
    /// </summary>
    public ICollection Items { get; }        
}

SelectedItemsChangedEventArgs : RoutedEventArgs

/// <summary>
/// Raised when the selected items collection is modified
/// </summary>
public class SelectedItemsChangedEventArgs : RoutedEventArgs
{        
    /// <summary>
    /// Items added to the collection
    /// </summary>
    public ICollection Added { get; }

    /// <summary>
    /// Items removed from the collection
    /// </summary>
    public ICollection Removed { get; }

    /// <summary>
    /// The selected items
    /// </summary>
    public ICollection Selected { get; }        
}

Fields

Dependency Property Description
AutoCompleteBackgroundProperty Identified the AutoCompleteBackground dependency property.
AutoCompleteForegroundProperty Identified the AutoCompleteForeground dependency property.
AutoCompleteMaxLengthProperty Identified the AutoCompleteMaxLength dependency property.
ClearFilterOnDropdownClosingProperty Identifies the ClearFilterOnDropdownClosing dependency property.
DropdownItemTemplateProperty Identifies the DropdownItemTemplate dependency property.
EnableAutoCompleteProperty Identified the EnableAutoComplete dependency property.
EnableFilteringProperty Identifies the EnableFiltering dependency property.
EnableGroupingProperty Identifies the EnableGrouping dependency property.
FilterServiceProperty Identifies the FilterService dependency property.
IsDropDownOpenProperty Identifies the IsDropDownOpen dependency property.
IsEditableProperty Identifies the IsEditable dependency property.
IsEditModeProperty Identifies the IsEditMode dependency property.
ItemsSourceProperty Identifies the ItemsSource dependency property.
MaxDropDownHeightProperty Identifies the MaxDropDownHeight dependency property.
SelectedItemsProperty Identifies the SelectedItems dependency property.
SelectedItemTemplateProperty Identifies the SelectedItemTemplate dependency property.
SelectionModeProperty Identified the SelectionMode dependency property.

Properties

Property Description
AllowDrop Gets or sets a value indicating whether this element can be used as the target of a drag-and-drop operation. This is a dependency property.
(Inherited from FrameworkElement)
AutoCompleteBackground Gets or sets background brush used when displaying the autocomplete content for the Filter Criteria
AutoCompleteForeground Gets or sets foreground brush used when displaying the autocomplete content for the Filter Criteria
AutoCompleteMaxLength Gets or sets the maximum length of autocomplete content displayed for the Filter Criteria
Background Gets or sets a brush that describes the background of a control.
(Inherited from Control)
BindingGroup Gets or sets the BindingGroup that is used for the element.
(Inherited from FrameworkElement)
BorderBrush Gets or sets a brush that describes the border background of a control.
(Inherited from Control)
BorderThickness Gets or sets the border thickness of a control.
(Inherited from Control)
ClearFilterOnDropdownClosing Gets or sets whether the Filter Criteria is cleared as the Dropdown Menu is closing while it has keyboard focus. (default) true
Clip Gets or sets the geometry used to define the outline of the contents of an element. This is a dependency property.
(Inherited from UIElement)
ClipToBounds Gets or sets a value indicating whether to clip the content of this element (or content coming from the child elements of this element) to fit into the size of the containing element. This is a dependency property.
(Inherited from UIElement)
CommandBindings Gets a collection of CommandBinding objects associated with this element. A CommandBinding enables command handling for this element, and declares the linkage between a command, its events, and the handlers attached by this element.
(Inherited from UIElement)
ContextMenu Gets or sets the context menu element that should appear whenever the context menu is requested through user interface (UI) from within this element.
(Inherited from FrameworkElement)
Cursor Gets or sets the cursor that displays when the mouse pointer is over this element.
(Inherited from FrameworkElement)
DataContext Gets or sets the data context for an element when it participates in data binding.
(Inherited from FrameworkElement)
DropdownItemTemplate Gets or sets the DataTemplate used to display each item in the Dropdown Menu list
EnableAutoComplete Gets or sets whether autocomplete feature is enabled for the Filter Criteria
EnableFiltering Gets or sets whether filtering is enabled
EnableGrouping Gets or sets whether grouping is enabled
Effect Gets or sets the bitmap effect to apply to the UIElement. This is a dependency property.
(Inherited from UIElement)
FilterService Gets or sets a custom filter service that is used when filtering items in the collection. If the filter service is null, then a default service is used that applies a filter on the override string ToString()
FlowDirection Gets or sets the direction that text and other user interface (UI) elements flow within any parent element that controls their layout.
(Inherited from FrameworkElement)
Focusable Gets or sets a value that indicates whether the element can receive focus. This is a dependency property.
(Inherited from UIElement)
FocusVisualStyle Gets or sets a property that enables customization of appearance, effects, or other style characteristics that will apply to this element when it captures keyboard focus.
(Inherited from FrameworkElement)
FontFamily Gets or sets the font family of the control.
(Inherited from Control)
FontSize Gets or sets the font size.
(Inherited from Control)
FontStretch Gets or sets the degree to which a font is condensed or expanded on the screen.
(Inherited from Control)
FontWeight Gets or sets the weight or thickness of the specified font.
(Inherited from Control)
ForceCursor Gets or sets a value that indicates whether this FrameworkElement should force the user interface (UI) to render the cursor as declared by the Cursor property.
(Inherited from FrameworkElement)
Foreground Gets or sets a brush that describes the foreground color.
(Inherited from Control)
Height Gets or sets the suggested height of the element.
(Inherited from FrameworkElement)
HorizontalAlignment Gets or sets the horizontal alignment characteristics applied to this element when it is composed within a parent element, such as a panel or items control.
(Inherited from FrameworkElement)
HorizontalContentAlignment Gets or sets the horizontal alignment of the control's content.
(Inherited from Control)
InputBindings Gets the collection of input bindings associated with this element.
(Inherited from UIElement)
InputScope Gets or sets the context for input used by this FrameworkElement.
(Inherited from FrameworkElement)
IsDropDownOpen Gets or sets a value that indicates whether the Dropdown Menu is currently open.
IsEditable Gets or sets a value that indicates whether the user can edit items in the Selected Items Panel. The default value is true.
IsEditMode Gets the value identifying the Visual State of the control (i.e. Readonly or EditMode)
IsEnabled Gets or sets a value indicating whether this element is enabled in the user interface (UI). This is a dependency property.
(Inherited from UIElement)
IsFocused Gets a value that determines whether this element has logical focus. This is a dependency property.
(Inherited from UIElement)
IsHitTestVisible Gets or sets a value that declares whether this element can possibly be returned as a hit test result from some portion of its rendered content. This is a dependency property.
(Inherited from FrameworkElement)
IsTabStop Gets or sets a value that indicates whether a control is included in tab navigation.
(Inherited from Control)
ItemsSource Gets or sets the collection used to generate the content of the listbox ItemsControl.
Language Gets or sets localization/globalization language information that applies to an element.
(Inherited from FrameworkElement)
LayoutTransform Gets or sets a graphics transformation that should apply to this element when layout is performed.
(Inherited from FrameworkElement)
Margin Gets or sets the outer margin of an element.
(Inherited from FrameworkElement)
MaxDropDownHeight Gets or sets the maximum height of the Sdl.MultiSelectComboBox dropdown menu
MaxHeight Gets or sets the maximum height constraint of the element.
(Inherited from FrameworkElement)
MaxWidth Gets or sets the maximum width constraint of the element.
(Inherited from FrameworkElement)
MinHeight Gets or sets the minimum height constraint of the element.
(Inherited from FrameworkElement)
MinWidth Gets or sets the minimum width constraint of the element.
(Inherited from FrameworkElement)
Name Gets or sets the identifying name of the element. The name provides a reference so that code-behind, such as event handler code, can refer to a markup element after it is constructed during processing by a XAML processor.
(Inherited from FrameworkElement)
Opacity Gets or sets the opacity factor applied to the entire UIElement when it is rendered in the user interface (UI). This is a dependency property.
(Inherited from UIElement)
OpacityMask Gets or sets an opacity mask, as a Brush implementation that is applied to any alpha-channel masking for the rendered content of this element. This is a dependency property.
(Inherited from UIElement)
OverridesDefaultStyle Gets or sets a value that indicates whether this element incorporates style properties from theme styles.
(Inherited from FrameworkElement)
Padding Gets or sets the padding inside a control.
(Inherited from Control)
RenderSize Gets (or sets) the final render size of this element.
(Inherited from UIElement)
RenderTransform Gets or sets transform information that affects the rendering position of this element. This is a dependency property.
(Inherited from UIElement)
RenderTransformOrigin Gets or sets the center point of any possible render transform declared by RenderTransform, relative to the bounds of the element. This is a dependency property.
(Inherited from UIElement)
Resources Gets or sets the locally-defined resource dictionary.
(Inherited from FrameworkElement)
SelectedItems Gets or sets the selected items.
SelectedItemTemplate Gets or sets the DataTemplate used to display each item in the Selected Items Panel
SelectionMode Gets or sets the SelectionMode value. The SelectionMode property determines how many items a user can select at one time. You can set the property to Multiple (the default) or Single
SnapsToDevicePixels Gets or sets a value that determines whether rendering for this element should use device-specific pixel settings during rendering. This is a dependency property.
(Inherited from UIElement)
Style Gets or sets the style used by this element when it is rendered.
(Inherited from FrameworkElement)
TabIndex Gets or sets a value that determines the order in which elements receive focus when the user navigates through controls by using the TAB key.(Inherited from Control)
Tag Gets or sets an arbitrary object value that can be used to store custom information about this element.
(Inherited from FrameworkElement)
Template Gets or sets a control template.
(Inherited from Control)
ToolTip Gets or sets the tool-tip object that is displayed for this element in the user interface (UI).
(Inherited from FrameworkElement)
Triggers Gets the collection of triggers established directly on this element, or in child elements.
(Inherited from FrameworkElement)
UseLayoutRounding Gets or sets a value that indicates whether layout rounding should be applied to this element's size and position during layout.
(Inherited from FrameworkElement)
VerticalAlignment Gets or sets the vertical alignment characteristics applied to this element when it is composed within a parent element such as a panel or items control.
(Inherited from FrameworkElement)
VerticalContentAlignment Gets or sets the vertical alignment of the control's content.
(Inherited from Control)
Visibility Gets or sets the user interface (UI) visibility of this element. This is a dependency property.
(Inherited from UIElement)
Width Gets or sets the width of the element.
(Inherited from FrameworkElement)

Events

Property Description
FilterTextChanged Occurs when the criteria of the filter text has changed. The FilterTextChangedEventArgs are passed with the event, identifying the filter criteria and list of items currently filtered.
SelectedItemsChanged Occurs when items in the selected items collection has changed. The SelectedItemsChangedEventArgs are passed with the event, identifying the added, removed and currently selected items.

Event Behaviours

We have introduced the following event behaviors to accommodate binding events to a command. This way, the bound command is invoked like an event handler when the event is raised.

Property Description
FilterTextChangedBehaviour.FilterTextChanged Occurs when the criteria of the filter text has changed. The FilterTextChangedEventArgs are passed with the event, identifying the filter criteria and list of items currently filtered.
SelectedItemsChangedBehaviour.SelectedItemsChanged Occurs when items in the selected items collection has changed. The SelectedItemsChangedEventArgs are passed with the event, identifying the added, removed and currently selected items.

multiselect-combobox's People

Contributors

ai191 avatar annaantal avatar cmonit avatar cornea-robert avatar cromica avatar danielklecha avatar dependabot[bot] avatar impertatore avatar iturisdl avatar lucyainsworth avatar mitchcapper avatar mrxx99 avatar remusp avatar ropop-rws avatar rwsdwatson avatar sdolhaor avatar skerestes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multiselect-combobox's Issues

How to bind sdl / Multiselect-ComboBox in simple WPF - MVVM

Dear sdl-Multiselect-ComboBox contributors,
Please let me how to bind your control in the following simple WPF โ€“ MVVM code below.
If the user type some characters of the intended search string, the โ€œsdl-Multiselect-ComboBoxโ€ would suggest a list of found items in its control. Any selection in multiple mode should be added to the DataGrid.
Thank you for your support in advance with
Kind regards

<Window x:Class="WpfMultiSelectComboBox.MainWindow"
        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:local="clr-namespace:WpfMultiSelectComboBox"
        xmlns:sdl="http://schemas.sdl.com/xaml"
        xmlns:vm="clr-namespace:WpfMultiSelectComboBox.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <vm:MainViewModel x:Key="mainVM"/>
            <BooleanToVisibilityConverter x:Key="BoolToVis"/>
        </ResourceDictionary>
    </Window.Resources>
    <Grid DataContext="{Binding Source={StaticResource mainVM}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
<TextBox  Text="Search TextBox with multiple choices, which should b substituted with sdl-Multiselect-ComboBox" />
<DataGrid Grid.Row="1"
                  ItemsSource="{Binding People, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
                  AutoGenerateColumns="False"
                  CanUserReorderColumns="False"
                  CanUserDeleteRows="False"
                  CanUserAddRows="False"
                  CanUserResizeRows="False"
                  CanUserResizeColumns="True"
                  CanUserSortColumns="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Width="*"/>
                <DataGridTextColumn Header="Age" Binding="{Binding Age, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Width="50"/>
            </DataGrid.Columns>
</DataGrid>
    </Grid>
</Window>

~\Models

namespace WpfMultiSelectComboBox.Models
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

~\ViewModels

namespace WpfMultiSelectComboBox.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        #region field
        private ObservableCollection<Person> _people = new ObservableCollection<Person>();
        private ObservableCollection<Person> _selectedPeople = new ObservableCollection<Person>();
        #endregion field

        #region ctor
        public MainViewModel()
        {
            CreatePeople();
        }
        #endregion ctor

        #region property
        public ObservableCollection<Person> People
        {
            get { return _people; }
            set
            {
                if (_people != value)
                {
                    _people = value;
                    OnPropertyChanged(nameof(People));
                }
            }
        }

        public ObservableCollection<Person> SelectedPeople
        {
            get { return _selectedPeople; }
            set
            {
                if (_selectedPeople != value)
                {
                    _selectedPeople = value;
                    OnPropertyChanged(nameof(SelectedPeople));
                }
            }
        }

        #endregion property

        #region method
        private void CreatePeople()
        {
            People = new ObservableCollection<Person>
            {
                new Person{ Name = "John", Age = 23},
                new Person{ Name = "Peter", Age = 20},
                new Person{ Name = "Oliver", Age = 22},
                new Person{ Name = "Stephan", Age = 35},
                new Person {Name = "Albert", Age = 45},
                new Person { Name = "Tony", Age = 46}
            };
        }
        #endregion method
    }
} 

Two binding mode is not working for SelectedItems

Scenario,
I have custom list of object which is binding with SelectedItems. At some condition, I am removing all items from custom list of object but still getting selected items in combox panel in font end

Alt+Up / Alt+Down for accessibility

Normal combo boxes can use the key combinations Alt+Up / Alt+Down to open / close the dropdown.
It would be nice for accessibility if the MultiSelectComboBox could do the same.

"ItemsSource" doesn't work correctly

When I assigned a value "ItemsSource" my programm stops when i tryed to navigate on page which contains "MultiSelectComboBox".
Thank you in advance! :)

SelectedItems property

Hi
How can I have SelectedItems in my ViewModel.
I bind the SelectedItems to a property in my viewmodel, but the setter never gets called.
I also tried this one:

<i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectedItemsChanged">
            <i:InvokeCommandAction Command="{Binding Path=SelectedItemsChangeCommand"} CommandParameter="{Binding ElementName=multiSelectComboBox, Path=SelectedItems}"/>
        </i:EventTrigger>
</i:Interaction.Triggers>

but the argument to my command is always same.
thanks in advance for your help.

When IsEditable and EnableFiltering are false the TextBox's caret and MultiSelectComboBox.SelectedItemsPanel.Readonly.Glyph.Template are visible

When IsEditable and EnableFiltering are false I think the control should act like a normal Combobox.

  • Instead of having a TextBox that cannot be used, maybe we can remove it from UI when IsEditable and EnableFiltering are false
  • Instead of MultiSelectComboBox.SelectedItemsPanel.Readonly.Glyph.Template it would be nicer to have as dropdown button the MultiSelectComboBox.SelectedItemsPanel.EditMode.Glyph.Template when IsEditable and EnableFiltering are false

UI freezes if multiselectcombobox is not visible when a piece of UI is loaded

I am working with the Mahapps UI api to show a custom dialog that contains an SDL multiselectcombobox. If the combobox is visible on dialog arrange/layout then the dialog will load & present without any issues; however if the combobox's visibility is collapsed then it will lock up the UI indefinitely. For the time being, my solution is to simply only use this control in containers that will always be visible on presentation, but it would be great if the visibility issues could be addressed.

Cheers!
-Lucy

Preselected items not selected in DropDown

I bind the SelectedItems property to an ObservableCollection, which is prefilled as soon the data object is loaded. It works partly, because they appear in the SelectedItems TextBlock, but they are not selected in the dropdown listbox. I can click the items of the listbox, they would be added to the selecteditems, but I can't get rid of the preselected (or programmatically selected) items. I tried it with system types like ints, but nothing changed.

Please see the attached screenshot, maybe its clearer then.
2
1

No results found

Hi There,

i am trying to implement this awesome Multiselect ComboBox. I followed the examples and have following setup
Inside my ViewModel I used the LanguageItem Class with all the Interfaces

`

        var group = new LanguageItemGroup(0, "All Items");
        Items = new ObservableCollection<LanguageItem>
         {
        new LanguageItem
        {
            Id = "en-US",
            Name= "English (United States)",
            Group = group
        },
        new LanguageItem
        {
            Id = "it-IT",
            Name= "Italian (Italy)",
            Group = group
        },
        new LanguageItem
        {
            Id = "de-DE",
            Name= "German (Germany)",
            Group = group
        }
    };`

My Items ObservableCollection looks like this
public ObservableCollection<LanguageItem> Items { get => _items ?? (_items = new ObservableCollection<LanguageItem>()); set { _items = value; OnPropertyChanged("Items"); } }

Inside XAML i used this Code
<sdl:MultiSelectComboBox DataContext="{Binding }" ItemsSource="{Binding Items}" IsEditable="true" SelectionMode="Multiple"/>

The Items Collection is correctly called and returns the 3 Items i initialized in the viewmodel, but the MultiSelectComboBox only shows "No results found"

NoResults

Cannot set BorderThickness

Hi,

I'm not sure if is not implemented or I'm doing something wrong. I tried to set BorderThickness because the requirement is to have border only on the bottom, but is not working.

Can you please, help me?

Thank you!

image

Can InputMethod be disabled?

I found that the codes
InputMethod.IsInputMethodEnabled="False" InputMethod.PreferredImeState="Off" do not work. Is there any method that could disable the input method?

"SelectedItems" always equals null

Hello!
As the name suggests, field of object of class "MultiSelectComboBox" such as "SelectedItems" always equals null.
My application include 3 buttons "Show all selected items", "Show first selected item" and "Show last selected item", and one MultiSelectComboBox.
When i picked few items, in "MultiSelectComboBox_SelectedItemsChanged" i wrote MessageBox.Show(multiSelectComboBox.SelectedItems.ToString());, and after next selection of item i get error : "SelectedItems" returned null .
Thank you in advance!

Port to .Net Core 3.0

Hi!
Is there a chance that You will move this library to next level and port it to .Net Core 3?
Best
Daniel

Filter is applied before the filter criteria is changed

While sequential input characters into the filter string, it takes as the filtering criteria the value of the text field that was BEFORE the last character was entered. I assume that the filter activation trigger is binded to the KeyDown event, and not to the filter criteria string changed event.

Changed list (Itemsource) in dialog

Hi,

Please help me with this situation. I am using this multicombobox in a dialog. I want to change the list in this multicombox in function of another selection of a combobox. I tried it, but the list remained the same. In the code, the list is changing.

Is this posiblle to achieve? Please tell me if I must add the code.

Thank you very much.

Have a nice day!

load on demand

First of all - control looks great!

I am wondering if you have plans to build on demand feature in this project.
I know thiat is complicated thing.

I worry that will be problem when I attach collection with 1 million records.
Do you have experience how it will work with your control?

Something similar is available in wpf.lazycombobox but it's the only feature of this control...

IItemGroup interface will complicate on-demand feature but control can pass to "SourceService" additional information with last group and read next package with items.

Best

Component not initialized if datacontext set before

I have spent half a day trying to understand why I had no elements in my project while the sample works.
The conclusion is that the component is not able to initialize itself if the datacontext is set before the initializecomponents method.
It would be nice to correct that...

Filter Service doesn't work immediately

Hi,

I have a little problem when I want to apply a custom filter service.
Apparently the filter is only applied after using the edit mode and then change the focus.
SetFilter runs immediately. However, the linked method is only applied after the described procedure.

This is my XAML:

<DataGridTemplateColumn Header="Users" x:Name="usercombo" Width="3*" Visibility="{Binding DataContext.IsAdmin, Source={x:Reference dummyElement}, Converter={StaticResource BoolToVis}, Mode=OneWay}">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <sdl:MultiSelectComboBox MinWidth="150" MinHeight="35" VerticalAlignment="Center" HorizontalAlignment="Center"
                                EnableFiltering="True"
                                FilterService="{Binding FilterService, diag:PresentationTraceSources.TraceLevel='High'}"
                                ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},            
                                Path=DataContext.AllAllowedUsers, Mode=OneWay}"  
                                EnableAutoComplete="False"
                                EnableGrouping="False"
                                IsEditable="True"
                                SelectionMode="Multiple"           
                                ClearFilterOnDropdownClosing="True"
                                DropdownItemTemplate="{StaticResource MultiSelectComboBox.Dropdown.ListBox.ItemTemplate}"
                                SelectedItemTemplate="{StaticResource MultiSelectComboBox.SelectedItems.ItemTemplate}"
                                SelectedItems="{Binding FancyUsers, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
                                </sdl:MultiSelectComboBox>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

This is my custom filter:

public class AdminFilter : IFilterService
    {

        public void SetFilter(string criteria)
        {
            ConfigureFilter();
        }

        public Predicate<object> Filter { get; set; }

        private bool FilteringByUserRole(object item)
        {
            FancyUser user = item as FancyUser;
            //Return user whose User-Role isn't Admin
            return (user.user.fk_user_role_id > 1);
        }

        private void ConfigureFilter()
        {
            Filter = FilteringByUserRole;
        }
    }

I apply the filter in my object after creating my ObservableCollection as follows:

FilterService = new AdminFilter();
NotifyPropertyChanged(nameof(FilterService));

In your example project the filter works immediately. Did I miss something? Thx

Dialog issue

Hi,

I'm not sure if is an issue here or I'm doing something wrong. I have a window which opens another window when i press button Test. This new window have a Multiselect-ComboBox, but when i open this window there are no items in the Multiselect-ComboBox.
I made a test on a test project because i don't know what the issue. The initial window:
image

From the second window(the same), I don't have any items.
image

I mention that I want to use it with dialoghost from materialDesign but because i didn't have any idea where is the issue, i test it with ShowDialog.

Thank you,
Simona

Paste text

Hi,

First, I should say the control looks and works great.

I was wondering how we can paste some items? I have tried to implement ApplicationCommands.Paste but it doesn't call/fire the relevant function.

<sdl:MultiSelectComboBox.CommandBindings> <CommandBinding Command="ApplicationCommands.Paste" Executed="CommandBinding_Executed" CanExecute="CommandBinding_CanExecute" /> </sdl:MultiSelectComboBox.CommandBindings>

Wrong bindings of SelectedItems

After I updated the sdl.multiselectcombobox to the latest version, I found a strange bug.
<sdl:MultiSelectComboBox ItemsSource="{Binding Collections}" SelectedItems="{Binding SelectedItems}" SelectionMode="Multiple"/>

In the ViewModel, I have this codes
...... SelectedItems = items;... Initially 'items' has 20 elements. After executing this line, 'SelectedItems' and 'items' only has the first element. While in the UI, there are still has 20 elements. When I use the earlier version, the bug does not exist. Hope you could help me out.

Many thanks!

.net6+Win10 comptiable

I use the latest version of MultiSelectComboBox. I'm using Win10 + .Net 6. However, I meet the error of
XamlX.XamlParseException: Unable to resolve type MultiSelectComboBox from namespace http://schemas.sdl.com/xaml
<sdl:MultiSelectComboBox Grid.Row="1" Grid.Column="1" Height="40" MinWidth="200" HorizontalAlignment="Stretch" EnableGrouping="False" />

Is there anything wrong when I'm using it.

BindingExpression Error 'IsEditMode'

Hi, first of all, nice control!! :)

I want to use it inside a datagrid in WPF. It works so far, but I cannot get rid of the error message:
"System.Windows.Data Error: 40 : BindingExpression path error: 'IsEditMode' property not found on 'object' ''ContentPresenter' (Name='')'. BindingExpression:Path=IsEditMode; DataItem='ContentPresenter' (Name=''); target element is 'TextBox' (Name=''); target property is 'IsEnabled' (type 'Boolean')"

My XAML looks like this:

 <DataGridTemplateColumn Header="Projects" x:Name="sdcombo">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <sdl:MultiSelectComboBox MinWidth="300" MinHeight="35"
                                ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},            
                                Path=DataContext.allProjects}"  
                                IsEditable="false"
                                SelectionMode="Multiple"           
                                EnableAutoComplete="False" 
                                EnableFiltering="False"
                                DropdownItemTemplate="{StaticResource MultiSelectComboBox.Dropdown.ListBox.ItemTemplate}"
                                SelectedItemTemplate="{StaticResource MultiSelectComboBox.SelectedItems.ItemTemplate}"
                                sdl:SelectedItemsChangedBehaviour.SelectedItemsChanged="{Binding ProjectsChangedCommand}"
                                SelectedItems="{Binding FancyProjects, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                            </sdl:MultiSelectComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
 </DataGridTemplateColumn>

The templates are fairly simple:

<DataGrid.Resources>
                <DataTemplate x:Key="MultiSelectComboBox.Dropdown.ListBox.ItemTemplate" DataType="h:FancyProject">
                    <TextBlock Text="{Binding Path=project.name}" FontSize="14"/>
                </DataTemplate>
                <DataTemplate x:Key="MultiSelectComboBox.SelectedItems.ItemTemplate" DataType="h:FancyProject">
                    <TextBlock  Text="{Binding Path=project.name}" FontSize="14"/>
                </DataTemplate>
</DataGrid.Resources>

Can you point me to where I miss something? Thanks in advance!

Add a SelectedItem Property

After using this project for several months, I found that the filtering service works so great that I would like to replace ComboBox with Multiselect-ComboBox in the single select mode. However, the SelectedItems only binds with IList. Could you add a property, SelectedItem, so I could use the single select mode better.

When ItemsSource is changed, popup list is not updated

Hi,
When MultiSelectComboBox::ItemsPropertyChangedCallback is executed, it creates new collection view and assign it to ItemsCollectionViewSource.
The problem is that _dropdownListBox.ItemsSource is not updated and is still pointing to a view created during initialization.

When I've added
_dropdownListBox.ItemsSource = ItemsCollectionViewSource?.View;
inside ItemsCollectionViewSource set method, popup updates.

Selecting all items results in a NullReferenceException

Steps to reproduce:

  1. Start the example project
  2. Select the first item in the dropdown
  3. Scroll to the end of the list
  4. Press Shift and select the last item

Exception:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference is not set to an instance of an object.
  Source=Sdl.MultiSelectComboBox
  StackTrace:
   at Sdl.MultiSelectComboBox.Themes.Generic.MultiSelectComboBox.DropdownListBoxPreviewMouseUp(Object sender, MouseButtonEventArgs e) in C:\Repos\Multiselect-ComboBox\MultiSelectComboBox\Sdl.MultiSelectComboBox\Themes\Generic\MultiSelectComboBox.cs:line 1362

Disabling virtualization for the listbox solves the issue (and is still fast enough for my scenario), but a proper code fix would be great.

MultiSelectComboBox with material design

Hi!
If you create a new wpf project and add material design and multiselectcombobox via nuget. Then add this code to App.xaml

<Application x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp1"
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <materialDesign:BundledTheme BaseTheme="Light" PrimaryColor="Green" SecondaryColor="Lime" />

                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml" />
                <ResourceDictionary Source="/ReactiveValidation.Wpf;component/Themes/Generic.xaml" />
                <ResourceDictionary Source="/Sdl.MultiSelectComboBox;component/Themes/Generic/MultiSelectComboBox.xaml"></ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

In MainWindow.xaml add MultiSelectComboBox, you get strange behavior.

<Grid>
    <sdl:MultiSelectComboBox ItemsSource="{Binding Colors}"
                             SelectedItems="{Binding SelectedColors}"
                             EnableAutoComplete="False"
                             SelectionMode="Multiple" />
</Grid>

vMqmghZ6IU

I think the problem is in the styles: toggle button width or textblock width. Have you ever encountered such behavior?

UpdateAutoCompleteFilterText uses ToString of the item

private void UpdateAutoCompleteFilterText(string criteria, object item) method uses ToString to autocomplete the items.

This would require an autocomplete service to have clean suggestions (and not the type of the classes by default)

Unable to open control with selected elements and leave it empty it single select is active

Hi,
I added pull request #33. As in header user cant do this two basic operations.
I described everything in pull request. I think that my changes fixes everything.

I leaved behavior that restore selected item when control lost locus and drop down is opened but I'm not sure if it's required. I can live with that but maybe somebody knows the reason why it's there.

Please review pull request and accept my changes.

Best,
Daniel

Unable to create control from code-behind

Hi,
I want to add MultiSelectComboBox control in code-behind - in my case it's behavior.
I have a problem because I set bindings before control is displayed.
OnApplyTemplate method is exacuted after bindings and because of that the list is empty.
What should I do to workaround this?
I can't add bindings in dispatcher action because on this step FrameworkElementFactory is sealed.
Thanks for help!

Here is my xaml:

<ContentControl x:Name="comboControl"/>

And my code behind

var comboBox = new FrameworkElementFactory(typeof(Themes.Generic.MultiSelectComboBox));
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.VisibilityProperty, Visibility.Visible);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.MaxDropDownHeightProperty, 300);
var items = new System.Collections.ObjectModel.ObservableCollection<string> { "a", "b", "c", "d" };
comboBox.SetBinding(Themes.Generic.MultiSelectComboBox.ItemsSourceProperty, new Binding { Source = items, Path = new PropertyPath("."), Mode = BindingMode.TwoWay });
var selectedItems = new System.Collections.ObjectModel.ObservableCollection<string>();
comboBox.SetBinding(Themes.Generic.MultiSelectComboBox.SelectedItemsProperty, new Binding { Source = selectedItems, Path = new PropertyPath("."), Mode = BindingMode.TwoWay });
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.EnableAutoCompleteProperty, true);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.ClearFilterOnDropdownClosingProperty, true);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.IsEditableProperty, false);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.EnableFilteringProperty, false);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.EnableGroupingProperty, false);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.ClearSelectionOnFilterChangedProperty, false);
comboBox.SetValue(Themes.Generic.MultiSelectComboBox.SelectionModeProperty, Themes.Generic.MultiSelectComboBox.SelectionModes.Multiple);
var controlTemplate = new ControlTemplate { VisualTree = comboBox };
controlTemplate.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send, (System.Action)(() => {
    //what should I do here?
}));
this.comboControl.Template = controlTemplate;

Restore .NET 4.7 compatibility?

The solution still builds for .NET 4.7 without problems, would you consider re-adding it to the targets so the NuGet package could be used with older versions?

Suggestion of Add a comparer

There are two instances(A & B) of a certain class. These two instances are exact the same, but they have different hash. Is it possible to add a comparer so that if A is selected, then B cannot be added.

Extending this to a Datagrid

Hi, extremely useful combobox that ive been looking for. I am trying to extend this to work with a datagrid but no luck. I have a really simplified project that implements this on a single combobox and it works. However whenever I try to use this in a datatemplate column, it crashes as soon as I select an item from the drop down.
Any hints? Im new to WPF.
WPFTestApp MultiComboBox.zip

Ability to customize item container

Is there a better way to remove rounded corners from selected item container other then overriding entire control template?
Would it be possible to add something like ItemContainerTemplate or ItemContainerStyle so it could be customized easier?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.