DataGrid Commanding

Topics: Prism v4 - WPF 4
Mar 24, 2011 at 4:35 PM

Hi,

I am using a DataGrid control with a Selected Command behavior (as used in Stocktrader RI) in order to raise a Command when the selected item changed.

 

<DataGrid ItemsSource="{Binding SortedDocuments}" RowHeaderWidth="0" AutoGenerateColumns="False" x:Name="dgResults" SelectionMode="Single" commands:Selected.Command="{Binding SelectDocumentCommand}"/>


This works so far, so when an item is selected in the DataGrid, the SelectedDocumentCommand is raised.

Now I want to achieve that the command is raised again if the already selected item is clicked again. Actually it doesn't, since the selected item doesn't change. Is there any event/possibility to get that? How can I determine if the already selected item is "selected" (clicked) again??

 

Best Regards
Andreas 

 

Mar 28, 2011 at 4:48 PM

Hi Andreas,

One possible way to fulfill your requirement could be to define the command in your DataGrid’s Item Template, for example, triggering the command when you click the items.

In order to do so, you need to access your command that resides in your ViewModel from within a DataTemplate (whose DataContext is overridden), therefore you should implement one of the possibilities described in the following threads:

Please, let us know if this information helps you.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic

 

Mar 28, 2011 at 5:19 PM

Hi Miguel,

thanks for replying! Just a moment ago I thoght about using a Command Behavior like the Selected behavior from Stocktrader RI, but execute the command on mouse action (instead of SelectionChanged) something like this (maybe another possibility):

<DataGrid ... commands:SelectorClicked.Command="{Binding DocumentSelectedCommand}"/>

 

SelectorClicked.cs

public static class SelectorClicked
    {
        private static readonly DependencyProperty SelectorClickedCommandBehaviorProperty = DependencyProperty.RegisterAttached(
            "SelectorClickedCommandBehavior",
            typeof(SelectorClickedCommandBehavior),
            typeof(Selected),
            null);

        public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
            "Command",
            typeof(ICommand),
            typeof(SelectorClicked),
            new PropertyMetadata(OnSetCommandCallback));

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Only works for selector")]
        public static void SetCommand(Selector selector, ICommand command)
        {
            selector.SetValue(CommandProperty, command);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Only works for selector")]
        public static ICommand GetCommand(Selector selector)
        {
            return selector.GetValue(CommandProperty) as ICommand;
        }

        private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var selector = dependencyObject as Selector;
            if (selector != null)
            {
                GetOrCreateBehavior(selector).Command = e.NewValue as ICommand;
            }
        }

        private static SelectorClickedCommandBehavior GetOrCreateBehavior(Selector selector)
        {
            var behavior = selector.GetValue(SelectorClickedCommandBehaviorProperty) as SelectorClickedCommandBehavior;
            if (behavior == null)
            {
                behavior = new SelectorClickedCommandBehavior(selector);
                selector.SetValue(SelectorClickedCommandBehaviorProperty, behavior);
            }

            return behavior;
        }
 

 

SelectorClickedCommandBehavior:

 

public class SelectorClickedCommandBehavior : CommandBehaviorBase<Selector>
    {
        public SelectorClickedCommandBehavior(Selector selectableObject)
            : base(selectableObject)
        {
            selectableObject.PreviewMouseLeftButtonUp += selectableObject_PreviewMouseLeftButtonUp;
        }

        void selectableObject_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // just for testing: cast selector to datagrid to get current item / selected item
            CommandParameter = (TargetObject as DataGrid).CurrentItem;
            if (CommandParameter != null)
                ExecuteCommand();
        }

    }

 


What do you think about this solution? Instead of handling the SelectionChanged event to execute the command I handle the mouse click.. Done a short test, seems to work. Good approach??

 

Kind Regards,
Andreas 

Mar 28, 2011 at 6:29 PM

Andreas,

Your approach seems to be a valid possibility to achieve your scenario. Thank you for sharing this solution with the rest of the community.

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic