HandyControl icon indicating copy to clipboard operation
HandyControl copied to clipboard

Access Selected Items in CheckComboBox

Open Yopler opened this issue 4 years ago • 6 comments

I try to access to the Selected Items of the CheckComboBox. The goal is, to be able to selected Columns of a Table that you want to show. It seem like there is no way to do it in a MVVM achitecture.

The first way I was thinking is : <hc:CheckComboBox SelectedItems="{Binding MySelectedList}" /> but according to the issue #485 the SelectedItems is not a Property.

I found another way that not working but suppose to ^^. It is to create a class Item with 2 properties : Name and Selected and link them to the Property DisplayMemberPath and SelectedValuePath, see example below :

Model/Item.cs

public class Item{
        public string Name { get; set; }
        public bool Selected { get; set; }
}

ViewModel/MainWindowViewModel.cs

public class MainWindowViewModel{
        public ObservableCollections<Item> MyItemList { get; set; } = new  ObservableCollections<Item>() {
                new Item() { Name = "column", Selected = true},
                new Item() { Name = "column", Selected = true},
                new Item() { Name = "column", Selected = false},
                new Item() { Name = "column", Selected = false},
        }
}

View/MainWindow.xaml

<hc:CheckComboBox Width="300" ItemsSource="{Binding MyItemList }" ShowClearButton="True" 
ShowSelectAllButton="True" MaxHeight="30" DisplayMemberPath="Name" SelectedValuePath="Selected"/>

Is there a way to access to Selected Items without using the code behind (.xaml.cs) ? Is there an improvement to make in the CheckComboBox ?

Yopler avatar Sep 03 '21 14:09 Yopler

have you solved this question?

imtect avatar Feb 07 '22 02:02 imtect

No. I finaly use it in code behind to be able to make it work.

Yopler avatar Feb 07 '22 09:02 Yopler

can you give me some example, i have no idea to make it, thanks a lot!!!!

imtect avatar Feb 08 '22 09:02 imtect

Hi 🖐,

Here a little exemple how I make it work :

MainWindow.xaml.cs :

public partial class MainWindow : Window
    {
        public List<Item> Items { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            Items = new List<Item>();
            for (int i = 0; i < 15; i++)
                Items.Add(new Item($"Item {i}", i));

            // Here CheckComboBox refer to the hc:CheckComboBox x:Name="CheckComboBox"
            CheckComboBox.ItemsSource = Items;

            // Here, I select the first three items
            for (int i = 0; i < 3; i++)
                CheckComboBox.SelectedItems.Add(Items[i]);
            
        }

        private void CheckComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (Item item in e.AddedItems)
                // For on each add Items
                // do what you want
            foreach (Item item in e.RemovedItems)
                // For on each removed Items
                // do what you want
        }
}

and the xaml : MainWindow.xaml :

<Window x:Class="Wpf_Test.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:Wpf_Test" 
        xmlns:hc="https://handyorg.github.io/handycontrol"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Background="Gray">
    <StackPanel>
        <hc:CheckComboBox x:Name="CheckComboBox"
                      SelectionChanged="CheckComboBox_SelectionChanged"
                      DisplayMemberPath="Name"
                      ShowClearButton="True"
                      ShowSelectAllButton="True"/>
    </StackPanel>
</Window>

Hope it can help !

Yopler avatar Feb 09 '22 11:02 Yopler

thanks very mush

imtect avatar Feb 09 '22 14:02 imtect

mvvm solutions:

here is : Attached Dependency Property

public class CheckComBoxHelper { static bool _isUpdating = false;

    public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(List<string>), typeof(CheckComBoxHelper),
            new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged)));

    public static List<string> GetSelectedItems(DependencyObject d)
    {
        return d.GetValue(SelectedItemsProperty) as List<string>;
    }

    public static void SetSelectedItems(DependencyObject d, List<string> value)
    {
        d.SetValue(SelectedItemsProperty, value);
    }

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CheckComboBox checkComboBox = d as CheckComboBox;

        if (!_isUpdating)
        {
            var result = e.NewValue as List<string>;
            checkComboBox.SelectedItems.Clear();
            if (result != null)
            {
                foreach (var item in (List<string>)e.NewValue)
                {
                    checkComboBox.SelectedItems.Add(item);
                }
            }
            else
            {
                checkComboBox.SelectedItems.Add(e.NewValue);
            }
        }
    }

    public static readonly DependencyProperty AttachProperty =
     DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(CheckComBoxHelper),
         new FrameworkPropertyMetadata(default(bool), new PropertyChangedCallback(OnAttached)));

    public static bool GetAttach(DependencyObject d)
    {
        return (bool)d.GetValue(AttachProperty);
    }

    public static void SetAttach(DependencyObject d, bool value)
    {
        d.SetValue(AttachProperty, value);
    }

    private static void OnAttached(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CheckComboBox checkComboBox = d as CheckComboBox;
        checkComboBox.SelectionChanged += CheckComboxSelectionChanged;
    }

    private static void CheckComboxSelectionChanged(object sender, RoutedEventArgs e)
    {
        CheckComboBox checkComboBox = sender as CheckComboBox;
        _isUpdating = true;
        List<string> temp = new List<string>();
        foreach (var item in checkComboBox.SelectedItems)
        {
            temp.Add(item.ToString());
        }
        SetSelectedItems(checkComboBox, temp);
        _isUpdating = false;
    }
}

xaml: <hc:CheckComboBox ItemsSource="{Binding CurrentUser.ModuleItems}" ShowSelectAllButton="True" common:CheckComBoxHelper.Attach="True" common:CheckComBoxHelper.SelectedItems="{Binding CurrentUser.SelectItems,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource CheckComboBoxPlus}" hc:InfoElement.Necessary="True" />

imtect avatar Feb 18 '22 13:02 imtect

closed in 7519c7e

NaBian avatar Sep 03 '22 10:09 NaBian