If you are developing WPF application MVVM way you might have noticed that Button Provide a Command property that can be set to a ICommand instance and the command will be executed when button is clicked. There is no inbuilt way to set a Command that can be executed when ComboBox selection is changed. I have coded a behaviour that can be used to achieve this. Below is the code for the behaviour.
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
public class SelectionChangedBehaviour
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(SelectionChangedBehaviour), new PropertyMetadata(PropertyChangedCallback));
public static void PropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
{
Selector selector = (Selector)depObj;
if (selector != null)
{
selector.SelectionChanged += new SelectionChangedEventHandler(SelectionChanged);
}
}
public static ICommand GetCommand(UIElement element)
{
return (ICommand)element.GetValue(CommandProperty);
}
public static void SetCommand(UIElement element, ICommand command)
{
element.SetValue(CommandProperty, command);
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Selector selector = (Selector)sender;
if (selector != null)
{
ICommand command = selector.GetValue(CommandProperty) as ICommand;
if (command != null)
{
command.Execute(selector.SelectedItem);
}
}
}
}
Set the command in xaml as shown below:
<ComboBox SelectionChangedBehaviour.Command="{Binding CommandImpl}">ComboBox>
This can be used for ListBox and ListView as well.
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
public class SelectionChangedBehaviour
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(SelectionChangedBehaviour), new PropertyMetadata(PropertyChangedCallback));
public static void PropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
{
Selector selector = (Selector)depObj;
if (selector != null)
{
selector.SelectionChanged += new SelectionChangedEventHandler(SelectionChanged);
}
}
public static ICommand GetCommand(UIElement element)
{
return (ICommand)element.GetValue(CommandProperty);
}
public static void SetCommand(UIElement element, ICommand command)
{
element.SetValue(CommandProperty, command);
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Selector selector = (Selector)sender;
if (selector != null)
{
ICommand command = selector.GetValue(CommandProperty) as ICommand;
if (command != null)
{
command.Execute(selector.SelectedItem);
}
}
}
}
Set the command in xaml as shown below:
<ComboBox SelectionChangedBehaviour.Command="{Binding CommandImpl}">ComboBox>
This can be used for ListBox and ListView as well.
Naveen,
ReplyDeleteyour code helped me a lot. I was looking for exactly this, to bind a selection changed event on a combobox to a custom command I wrote on a RichTextBox.
Thanks.
Thank you! it helped
ReplyDeletethanks
ReplyDeleteI am getting CommandConverter cannot convert from System.String Error in the XAML . Any ideas?
ReplyDeleteICommand _modeSelectChanged;
public ICommand ModeSelectChanged
{
get
{
if (_modeSelectChanged == null)
{
_modeSelectChanged = new DelegateCommand(
this.OnModeSelectChangedCommandExecute,
this.OnModeSelectChangedCommandCanExecute);
}
return _modeSelectChanged;
}
}
private bool OnModeSelectChangedCommandCanExecute(object obj)
{
return true;
}
private void OnModeSelectChangedCommandExecute(object obj)
{
}
Above post would not show my XAML, here is the text, don't think this blogger likes the less than symbols so have removed in this post
ReplyDeleteComboBox Name="ResampleCombo" Grid.Column="4" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Path=ResampleMode}" Behave:SelectionChangedBehaviour.Command="ModeSelectChanged">
Ok I sorted it . I needed
ReplyDeleteBehave:SelectionChangedBehaviour.Command="{Binding ModeSelectChanged}"
Sorry, I missed the {Binding } construct in xaml. I have updated the post now. Thanks for sharing it.
ReplyDeleteDoes anybody have an idea why:
ReplyDeletenew PropertyMetadata(PropertyChangedCallback)
doesn't work in VB.NET?
It needed AddressOf.
ReplyDeleteHi,
ReplyDeleteI did the same for ComboBoxItem, but it not works when itemssource binding. Because the base type for command is ComboBoxItem but my items are simple models. Any idea?
Can you please explain how to use this? Where do you place this class? If I just type the provided XAML code it will not recognize the SelectionChangedBehaviour.
ReplyDeleteNaveen,
ReplyDeleteCan you PLEASE put a correct XAML example in this post. The XAML you have above is NOT in correct syntax.
Thank you.
Thank you very much! It helped
ReplyDeleteAwesome, this is an approved set of code this works very well in combination with my custom command handler; granted there are a few things that have to be coded correctly in order for things to fully comply yet if you know what you're doing it should be a breeze, great work Naveen!!!
ReplyDeleteI get "Behave" is not supported by WPF .. any idea ?
ReplyDeleteGreat !!!
ReplyDeleteThanks a lot, it helped a lot.
ReplyDeleteTis is a long shot as this is an old blog.... but could you perhaps explain how the SelectionChangedBehaviour class can be associated with a a specific ComboBox in CODE BEHIND? I have created a UserControl with 3 comboboxes in it and I want each of them to be bound to the SelectionChangedBehaviour.Command call-back
ReplyDelete