誰かにとって明らかな問題であることを願っています。ユーザーが ListBox 内の ListBoxItem をダブルクリックしたときに Edit コマンドが起動するようにします。以前にユーザーコントロールでこれを行ったことがありますが、これは十分に単純なListBoxであるため、VIEWで直接実行したいと考えています。しかし、それは配線されません。
リストボックスは次のとおりです。
<ListBox SelectedItem="{Binding DataQuerySortSelected}"
ItemContainerStyle="{StaticResource SortListItemStyle}"
ItemsSource="{Binding DataQueryHolder.DataQuerySorts}">
<ListBox.InputBindings>
<KeyBinding Key="Delete" Command="{Binding DataQuerySortDelete}" />
</ListBox.InputBindings>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="AllowDrop" Value="True" />
<EventSetter Event="PreviewMouseMove" Handler="DragDropListBoxItem_PreviewMouseMoveEvent" />
<EventSetter Event="Drop" Handler="DragDropListBoxItem_Drop" />
</Style>
</ListBox.Resources>
</ListBox>
最上位の Delete Key バインディングが正常に機能することに注意してください。参照されているスタイルは次のとおりです (個別の ResourceDictionary として取り込まれましたが、スタイルをインラインに配置しても違いはありません)。
<Style x:Key="SortListItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="MainBorder">
<ContentPresenter>
<ContentPresenter.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataQuerySortEdit}" />
</ContentPresenter.InputBindings>
</ContentPresenter>
<Border.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataQuerySortEdit}" />
</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>
違いがあるかどうかを確認するために、マウスバインディングを2か所に配置しましたが、違いはありません. そこには配線が一切ありません。他のすべては期待どおりに機能します。ビューでプレーン ボタンを作成し、それを DataQuerySortEdit コマンドにポイントすると、期待どおりに機能します。
何か不足していますか?助けてくれてありがとう。
編集:Jの応答に応じて、さらに情報を追加するだけです。ControlTemplate の Border に最も近いリストボックスに相対的なバインディングを与え、リストボックスに名前を付けて、出力がそれを見つけることを確認できるようにしました。これは出力ウィンドウでした:
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''DataQuerySort' (HashCode=7641038)'. BindingExpression:Path=DataQuerySortEdit; DataItem='DataQuerySort' (HashCode=7641038); target element is 'MouseBinding' (HashCode=65119131); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''DataQuerySort' (HashCode=50439840)'. BindingExpression:Path=DataQuerySortEdit; DataItem='DataQuerySort' (HashCode=50439840); target element is 'MouseBinding' (HashCode=3649016); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''DataQuerySort' (HashCode=65588106)'. BindingExpression:Path=DataQuerySortEdit; DataItem='DataQuerySort' (HashCode=65588106); target element is 'MouseBinding' (HashCode=35717517); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''DataQuerySort' (HashCode=32836053)'. BindingExpression:Path=DataQuerySortEdit; DataItem='DataQuerySort' (HashCode=32836053); target element is 'MouseBinding' (HashCode=66172851); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''ListBox' (Name='SortListBox')'. BindingExpression:Path=DataQuerySortEdit; DataItem='ListBox' (Name='SortListBox'); target element is 'MouseBinding' (HashCode=28263486); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''ListBox' (Name='SortListBox')'. BindingExpression:Path=DataQuerySortEdit; DataItem='ListBox' (Name='SortListBox'); target element is 'MouseBinding' (HashCode=27134857); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''ListBox' (Name='SortListBox')'. BindingExpression:Path=DataQuerySortEdit; DataItem='ListBox' (Name='SortListBox'); target element is 'MouseBinding' (HashCode=7437765); target property is 'Command' (type 'ICommand')
System.Windows.Data Error: 40 : BindingExpression path error: 'DataQuerySortEdit' property not found on 'object' ''ListBox' (Name='SortListBox')'. BindingExpression:Path=DataQuerySortEdit; DataItem='ListBox' (Name='SortListBox'); target element is 'MouseBinding' (HashCode=58400697); target property is 'Command' (type 'ICommand')
したがって、バインドの 2 回目の試み (Border InputBinding のものと推測しています) は、適切なリストボックスを正常に処理しますが、それでも ICommand を見つけることができません。ウィンドウ、リストを含むGirdなどに対して相対検索を試みましたが、それでも配線できません。また、Jが相対検索をMouseBindingsに直接入れるように言及したように試みましたが、同じエラーが発生しました。
EDIT2:MVVMLightを使用したViewModelのコマンドとプロパティは次のとおりです
public DataQuerySort DataQuerySortSelected
{
get { return _DataQuerySortSelected; }
set { NotifySetProperty(ref _DataQuerySortSelected, value, () => DataQuerySortSelected); }
}
private DataQuerySort _DataQuerySortSelected;
public RelayCommand DataQuerySortEdit
{
get { return new RelayCommand(_DataQuerySortEdit, CanDataQuerySortEdit); }
}
private void _DataQuerySortEdit()
{
DataQuerySortHolder = DataQuerySortSelected.Copy();
DataQuerySortEditMode = EditMode.Edit;
}
private bool CanDataQuerySortEdit()
{
return DataQuerySortSelected != null;
}
CanDataQuerySortEdit を取り出しても違いはありません。ボタンを作成してポイントすると機能するため、すべてが機能することを知っています。もちろん、ListBoxItemsの外側をクリックする限り、動作するDeleteキーのようなマウスのListBoxにinputbindingも作成すると。
EDIT3:これは、クラス、データコンテキスト、およびリソースを含むビュー自体の一部です。「{x:Type Window}」および「{x:Type l:ToolkitWindowBase}」になるように相対バインディングを試みました。ToolkitWindowBase は Window を直接拡張します。frmDataBrowserViewModel は、MVVMLight から ViewModelBase を拡張する ToolkitViewModelBase というクラスを拡張します。
<l:ToolkitWindowBase x:Class="GISToolkit.frmDataBrowser" x:Name="mainWindow" Icon="Images/favicon.ico"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d"
xmlns:l="clr-namespace:GISToolkit;assembly="
xmlns:lc="clr-namespace:GISToolkit.Controls;assembly="
xmlns:ls="clr-namespace:GISToolkit.Settings;assembly="
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:xctk="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
xmlns:xctkp="clr-namespace:Xceed.Wpf.Toolkit.Primitives;assembly=Xceed.Wpf.Toolkit"
Title="Solutions GIS Toolkit - Setup"
ResizeMode="CanResizeWithGrip" Foreground="White"
l:ControlBox.HasMaximizeButton="False" l:ControlBox.HasMinimizeButton="False" l:ControlBox.HasCloseButton="False"
Height="{Binding RunTimeHeight, Mode=TwoWay}"
Width="{Binding RunTimeWidth, Mode=TwoWay}" IsSettingsDirty="{Binding IsCurrentSettingsDirty}" IsEnabled="True">
<Window.DataContext>
<l:frmDataBrowserViewModel />
</Window.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/DataBrowser.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
..................
<l:ToolkitWindowBase />
EDIT4: 誰かがまだリストに載っている場合に備えて、「BindingTestWindow」という単一のウィンドウと「MainWindowViewModel」というビューモデルを持つ「WpfMvvmApplication1」という新しい WPF プロジェクトを作成してください。ファイル/プロジェクトに別の名前を使用していない限り、カット/ペースト):
<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"
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}" />
</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, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</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>
VIEWMODEL の場合:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq.Expressions;
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() { System.Diagnostics.Debugger.Break(); }
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;
}
}
これには他に何もありません。inputbinding が listboxtiem 内にある場合はバインディング エラーが発生しますが、たとえばリストボックス自体にある場合は発生しません。出力がFindAncestorでウィンドウを見つけたと言っているので、うまくいくはずです。