Intersoft ClientUI Documentation
How-to: Implement Selected Items Converter in UXMultipleSelectionComboBox

This example shows how to implement selected items converter in UXMultipleSelectionComboBox.

Example

Description

Selected item converter allows you to bind a collection of items where the selected item type is different with the search result type. In this example, you will learn how to implement this feature on a situation where you need to display the records from a table, but the data is supplied from another table that logically linked to a foreign key. See UXMultipleSelectionComboBox Overview to learn more about UXMultipleSelectionComboBox.

Scenario

In this scenario, suppose you want to make an application that have a feature to update the user's roles where a user can have more than one roles. In the common editing scenario, it will initially display the selected roles of the user. Later on, you can add or remove the roles of the user through the UXMultipleSelectionComboBox control.

The following illustration gives you a better explanation about the data model that will be used.

Based on the scenario above, you must have a data from UserRole table that contains the user's roles. First, you need to bind it to the SelectedItems property of UXMultipleSelectionComboBox, and then supply all possible roles that as the items source of the combobox control for user choices.

The SelectedItemConverter is used to convert the item from the selected items (UserRole) to the supplied roles data, which is exactly known to be different. You must create your own converter to convert the Role entity into UserRole entity and bind it into SelectedItemConverter property.

CS
Copy Code
public class UserRoleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Role role = value as Role;

        if (role != null && !value.GetType().Name.Equals("UserRole"))
        {
            return new UserRole() { RoleID = role.RoleID, Role = role };
        }

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Note that you also need to extend your UserRole data model to explicitly include the Role model property that is marked as DisplayMemberPath, because UserRole data model doesn't have this property.

CS
Copy Code
public sealed partial class UserRole
{
    public string Name
    {
        get
        {
            if (this.Role != null)
                return this.Role.Name;
            else
                return null;
        }
    }
}

Code

The following code shows you how to implement selected item converter in scenario explained above.

XAML
Copy Code
</UserControl.Resources>
    <Converters:UserRoleConverter x:Key="UserRoleConverter"/>
</UserControl.Resources>

<Grid x:Name="LayoutRoot">
    <Intersoft:UXMultipleSelectionComboBox SearchResult="{Binding Roles}" DisplayMemberPath="Name"
        FilterDescriptors="{Binding RoleLookUpDescriptor.FilterDescriptors, Mode=TwoWay}"
        SortDescriptors="{Binding RoleLookUpDescriptor.SortDescriptors, Mode=TwoWay}"
        PageDescriptor="{Binding RoleLookUpDescriptor.PageDescriptor}"
        SelectedItems="{Binding SelectedItems, Mode=TwoWay}" SelectedValuePath="RoleID"
        AutoFilterSelectedItems="True">

        <Intersoft:UXMultipleSelectionComboBox.Columns>
            <Intersoft:UXDataComboBoxTextColumn Header="Role" Binding="{Binding Name}" Width="100"/>
            <Intersoft:UXDataComboBoxTextColumn Header="Description" Binding="{Binding Description}" Width="280"/>
        </Intersoft:UXMultipleSelectionComboBox.Columns>

        <Intersoft:UXMultipleSelectionComboBox.DataContext>
            <ViewModels:UserRoleViewModel/>
        </Intersoft:UXMultipleSelectionComboBox.DataContext>

        <Intersoft:UXMultipleSelectionComboBox.SelectedItemConverter>
            <Converters:UserRoleConverter/>
        </Intersoft:UXMultipleSelectionComboBox.SelectedItemConverter>

    </Intersoft:UXMultipleSelectionComboBox>
</Grid>
CS
Copy Code
using System;
using System.Collections;
using Intersoft.Client.Data.ComponentModel;
using Intersoft.ClientUI.Samples.DataControls.ModelServices;

namespace Intersoft.ClientUI.Samples.DataControls.ViewModels
{
    public class UserRoleViewModel : ViewModelBase
    {
        #region Constructors

        public UserRoleViewModel()
        {
            this.RolesSource = RolesRepository.Instance;
            this.UserRolesSource = UserRolesRepository.Instance;
            this.Presenter = new MessagePresenter();
            this.RoleLookUpDescriptor = new QueryDescriptor();

            // Initialize Sort Descriptor
            this.RoleLookUpDescriptor.SuspendQueryChanged = true;
            this.RoleLookUpDescriptor.SortDescriptors.Add(new SortDescriptor() { PropertyName = "RoleID", Direction = ListSortDirection.Ascending });
            this.RoleLookUpDescriptor.SuspendQueryChanged = false;

            this.InitializeSelectedItems();
        }

        #endregion

        #region Fields

        private QueryDescriptor _roleLookUpDescriptor;
        private IEnumerable _roles;
        private INotifyCollectionChanged _selectedItems;

        #endregion

        #region Properties

        protected IDataRepository RolesSource { get; set; }
        protected IDataRepository UserRolesSource { get; set; }

        public QueryDescriptor RoleLookUpDescriptor
        {
            get { return _roleLookUpDescriptor; }
            set
            {
                if (_roleLookUpDescriptor != value)
                {
                    if (_roleLookUpDescriptor != null)
                        _roleLookUpDescriptor.QueryChanged -= new EventHandler(OnRoleLookUpQueryChanged);

                    _roleLookUpDescriptor = value;
                    _roleLookUpDescriptor.QueryChanged += new EventHandler(OnRoleLookUpQueryChanged);

                    OnPropertyChanged("RoleLookUpDescriptor");
                }
            }
        }

        public IEnumerable Roles
        {
            get { return this._roles; }
            set
            {
                if (_roles != value)
                {
                    _roles = value;
                    OnPropertyChanged("Roles");
                }
            }
        }

        public INotifyCollectionChanged SelectedItems
        {
            get { return _selectedItems; }
            set
            {
                if (_selectedItems != value)
                {
                    _selectedItems = value;
                    OnPropertyChanged("SelectedItems");
                }
            }
        }

        #endregion

        #region Methods

        private void OnRoleLookUpQueryChanged(object sender, EventArgs e)
        {
            this.RolesSource.GetData
            (
                this.RoleLookUpDescriptor,
                (roles) =>
                {
                    if (this.RoleLookUpDescriptor.PageDescriptor.PageIndex > 0)
                    {
                        ObservableCollection<object> items = this.Roles as ObservableCollection<object>;
                        foreach (var role in roles)
                        {
                            items.Add(role);
                        }
                    }
                    else
                    {
                        ObservableCollection<object> items = new ObservableCollection<object>(roles.Cast<object>());
                        this.Roles = items;
                    }
                },
                (totalItemCount) =>
                {
                    if (totalItemCount != -1)
                        this.RoleLookUpDescriptor.PageDescriptor.TotalItemCount = totalItemCount;
                },
                (error) =>
                {
                    this.Presenter.ShowErrorMessage(
                        "An exception has occurred during data loading\n." +
                        "Message: " + error.Message +
                        "Stack Trace: " + error.StackTrace);
                }
            );
        }

        private void InitializeSelectedItems()
        {
            //Get First User and it's Role from Data Source
            QueryDescriptor queryDescriptor = new QueryDescriptor();
            queryDescriptor.FilterDescriptors.Add(new FilterDescriptor("UserID", FilterOperator.IsEqualTo, 1));

            this.UserRolesSource.GetData
            (
                queryDescriptor,
                (userRoles) =>
                {
                    ObservableCollection<UserRole> collection = new ObservableCollection<UserRole>();

                    foreach (UserRole userRole in userRoles)
                    {
                        collection.Add(userRole);
                    }
                    this.SelectedItems = collection;
                }
            );
        }

        #endregion
    }
}

Results

The code above will produce the results which will look like the following image:

See Also

Concepts