から継承するカスタムWPFコントロールがありListView
ます。このコントロールのそれぞれListViewItem
に他のそのようなコントロールを含めることができ、これは無限に続く可能性があります。
カスタムListView
サブクラスにはCommandBinding
、切り取り、コピー、貼り付けの3つの機能と、ContextMenu
これらの各コマンドを発行する機能があります。すべてがトップレベルで期待どおりに機能します-切り取り、コピー、貼り付けができます。ただし、ネストされたListView
子孫コントロールの1つを右クリックして、[貼り付け]を選択すると(他の2つは同じように機能しますが)、次のいずれかが発生します。
コントロールにListViewItem
sが選択されていない場合、CommandExecuted
イベントは上部ListView
をとして発生しCommandTarget
ます。コントロールに選択されている場合ListViewItem
、すべてが正常に機能します。
これは既知の問題ですか?(まともな)回避策はありますか?ありがとう。
編集要求に応じて、ここに例があります:
カスタムListView
サブクラス:
public class MyListView : ListView
{
public MyListView()
{
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Copy,
CopyCommand_Executed, CopyCutCommand_CanExecute));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste,
PasteCommand_Executed, PasteCommand_CanExecute));
this.Background = new SolidColorBrush(Colors.Ivory);
}
MyListItem Binding
{
get { return this.DataContext as MyListItem; }
}
private void CopyCutCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Handled)
return;
e.CanExecute = (this.SelectedItems.Count > 0);
e.Handled = true;
}
private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Handled)
return;
if (this.SelectedItems.Count < 0)
return; // Nothing selected
List<MyListItem> items = new List<MyListItem>();
foreach (MyListItem str in this.SelectedItems)
items.Add(str);
Clipboard.SetData("Stuff", items);
e.Handled = true;
}
private void PasteCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Handled)
return;
e.CanExecute = Clipboard.ContainsData("Stuff");
e.Handled = true;
}
private void PasteCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Handled)
return;
MyListView lv = this;
List<MyListItem> strings = Clipboard.GetData("Stuff") as List<MyListItem>;
if (strings == null)
return;
foreach (MyListItem s in strings)
this.Binding.Items.Add(s);
e.Handled = true;
}
}
単純なListViewItem
バインディングクラス:
[Serializable]
public class MyListItem
{
public MyListItem() { this.Items = new ObservableCollection<MyListItem>(); }
public string Caption { get; set; }
public ObservableCollection<MyListItem> Items { get; set; }
}
XAML for MyControl
(コードビハインドなし)、それぞれの表現ListViewItem
:
<UserControl x:Class="TestNestedListView.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestNestedListView">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=Caption}" />
<local:MyListView Padding="10" ItemsSource="{Binding Path=Items}"/>
</StackPanel>
</Grid>
</UserControl>
MainWindow
XAML:
<Window x:Class="TestNestedListView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestNestedListView"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:MyListItem}">
<local:MyControl DataContext="{Binding}" />
</DataTemplate>
<Style TargetType="local:MyListView">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<local:MyListView x:Name="lv" ItemsSource="{Binding Path=Items}">
<local:MyListView.ContextMenu>
<ContextMenu>
<MenuItem Command="Copy" />
<MenuItem Command="Paste" />
</ContextMenu>
</local:MyListView.ContextMenu>
</local:MyListView>
</Window>
MainWindow
コードビハインド:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyListItem root = new MyListItem();
MyListItem item = new MyListItem() { Caption = "Item 1" };
item.Items.Add(new MyListItem() { Caption = "Subitem 1.1" });
root.Items.Add(item);
root.Items.Add(new MyListItem() { Caption = "Item 2" });
root.Items.Add(new MyListItem() { Caption = "Item 3" });
root.Items.Add(new MyListItem() { Caption = "Item 4" });
item = new MyListItem() { Caption = "Item 5" };
item.Items.Add(new MyListItem() { Caption = "Subitem 5.1" });
item.Items.Add(new MyListItem() { Caption = "Subitem 5.2" });
root.Items.Add(item);
lv.DataContext = root;
}
}
これが実際に動作していることを確認するには、右クリックして任意のアイテムをコピーします。ListView
次に、[アイテム2]の下の長方形(これは)を右クリックして、[貼り付け]をクリックします。新しいアイテムは、トップレベルの最後のアイテムとして貼り付けられることに注意してください。「サブアイテム1.1」の下の長方形を右クリックし、アイテムが「サブアイテム1.1」ではなく、「アイテム1」の子として貼り付けられていることに注意してください。