Quantcast
Channel: Windows Presentation Foundation (WPF) forum
Viewing all articles
Browse latest Browse all 18858

ListBoxItem MouseBinding in ControlTemplate InputBinding not Working MVVM

$
0
0

I have a WPF .NET 4.5 app.  I am trying to bind the mouse double click on a ListBoxItem but it does not work.  To demonstrate I created a brand new WPF project in VS2012 called "WpfMvvmApplication1" with a VIEW called "BindingTestWindow.xaml" and a VIEWMODEL called "BindingTestViewModel.cs".

The VIEW:

<Window x:Class="WpfMvvmApplication1.BindingTestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:WpfMvvmApplication1"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        Title="BindingTestWindow" Height="300" Width="300"><Window.DataContext><l:BindingTestViewModel /></Window.DataContext><Grid><GroupBox Header="Sorting:" ><Grid><ListBox Background="White" Name="SortListBox" ItemsSource="{Binding TestCollection}"><ListBox.InputBindings><KeyBinding Key="Delete" Command="{Binding TestCommand}" /><MouseBinding Gesture="LeftDoubleClick" Command="{Binding TestCommand, diag:PresentationTraceSources.TraceLevel=High}" /></ListBox.InputBindings><ListBox.Resources><Style TargetType="{x:Type ListBoxItem}"><Setter Property="AllowDrop" Value="True" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="ListBoxItem"><Border Name="MainBorder" Padding="0" Margin="0"><ContentPresenter /><Border.InputBindings><MouseBinding Gesture="LeftDoubleClick" Command="{Binding TestCommand, diag:PresentationTraceSources.TraceLevel=High}" /></Border.InputBindings></Border><ControlTemplate.Triggers><Trigger Property="IsSelected" Value="True"><Setter TargetName="MainBorder" Value="Yellow" Property="Background" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></ListBox.Resources></ListBox></Grid></GroupBox></Grid></Window>

The VIEWMODEL:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Input;

namespace WpfMvvmApplication1
{
    public class BindingTestViewModel : NotificationObject
    {
        public BindingTestViewModel()
        {
            TestCollection = new ObservableCollection<string>();
            for (int i = 0; i < 10; i++ )
                TestCollection.Add("test" + i);
        }

        public ICommand TestCommand { get { return new DelegateCommand(_TestCommand); } }

        private void _TestCommand() { MessageBox.Show("Worked!"); }

        public ObservableCollection<string> TestCollection
        {
            get { return _TestCollection; }
            set 
            {
                _TestCollection = value;
                RaisePropertyChanged(() => TestCollection);
            }
        }
        private ObservableCollection<string> _TestCollection;
    }

    public class DelegateCommand : ICommand
    {
        private readonly Action _command;
        private readonly Func<bool> _canExecute;
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public DelegateCommand(Action command, Func<bool> canExecute = null)
        {
            if (command == null)
                throw new ArgumentNullException();
            _canExecute = canExecute;
            _command = command;
        }

        public void Execute(object parameter)
        {
            _command();
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute();
        }

    }

    public class NotificationObject : INotifyPropertyChanged
    {
        protected void RaisePropertyChanged<T>(Expression<Func<T>> action)
        {
            var propertyName = GetPropertyName(action);
            RaisePropertyChanged(propertyName);
        }

        private static string GetPropertyName<T>(Expression<Func<T>> action)
        {
            var expression = (MemberExpression)action.Body;
            var propertyName = expression.Member.Name;
            return propertyName;
        }

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

That is pretty all you need to reproduce the app.  Run it and try double clicking on one of the items in the listbox.  Nothing will happen.  Try double clicking below the last item but inside the listbox - the ListBox double click binding works. 

Here is the ouput of the binding error

System.Windows.Data Warning: 80 : BindingExpression (hash=19883454): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=19883454): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=19883454): TransferValue - using final value <null>
System.Windows.Data Warning: 56 : Created BindingExpression (hash=56514700) for Binding (hash=35751240)
System.Windows.Data Warning: 58 :   Path: 'TestCommand'
System.Windows.Data Warning: 60 : BindingExpression (hash=56514700): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=56514700): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=56514700): Attach to System.Windows.Input.MouseBinding.Command (hash=35401344)
System.Windows.Data Warning: 64 : BindingExpression (hash=56514700): Use Framework mentor <null>
System.Windows.Data Warning: 67 : BindingExpression (hash=56514700): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=56514700): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=56514700): Resolve source deferred
System.Windows.Data Warning: 95 : BindingExpression (hash=56514700): Got InheritanceContextChanged event from MouseBinding (hash=35401344)
System.Windows.Data Warning: 67 : BindingExpression (hash=56514700): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=56514700): Found data context element: Border (hash=42168981) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=56514700): Activate with root item 'test9'
System.Windows.Data Warning: 108 : BindingExpression (hash=56514700):   At level 0 - for String.TestCommand found accessor <null>
System.Windows.Data Warning: 108 : BindingExpression (hash=56514700):   At level 0 - for EnumerableCollectionView.TestCommand found accessor <null>
System.Windows.Data Warning: 108 : BindingExpression (hash=56514700):   At level 0 - for Char.TestCommand found accessor <null>
System.Windows.Data Error: 40 : BindingExpression path error: 'TestCommand' property not found on 'object' ''String' (HashCode=-1556461388)'. BindingExpression:Path=TestCommand; DataItem='String' (HashCode=-1556461388); target element is 'MouseBinding' (HashCode=35401344); target property is 'Command' (type 'ICommand')

Is it just not possible to do like this in directly in a view?  I have done pretty much the exact same thing in a user control with a dependency property.  The DP is an ICommand that wires to the inputgesture when give a value when the user control is inserted into a window.  Why wouldnt I be able to do it directly in a view?

Thanks

Ernie


Viewing all articles
Browse latest Browse all 18858

Trending Articles