0

私はいくつかのオブジェクトを含むユーザー コントロールを持っていdCB_Propsます。最も重要なのは、Observable Collection にバインドされた ComboBox です。コレクションは任意のオブジェクトを取ることができますが、通常は と呼ばれる UserControl を取りますEditDeleteItemdCB_Propsとして使用するように設定しEditDeleteItemましたItemsTemplateが、イベントが発生しません。一方、インスタンスを追加するとEditDeleteItem、イベントが発生します。EditDeleteItem は他のコントロールをホストし、別の DataTemplates を使用する必要があるため、この方法で項目を追加することはできません。

EditDeleteItemには、 と という 2 つのルーティング イベントがEditClickありDeleteClickます。

コレクションが変更されると、追加されたアイテムのタイプが であるかどうかを確認するイベントが発生しますEditDeleteItem。その場合は、前述の 2 つのイベントにハンドラーを追加します。

EditDeleteClick の xaml の一部:

<WrapPanel x:Name="wp" HorizontalAlignment="Right" Visibility="Hidden" VerticalAlignment="Center" Margin="0,0,5,0">
    <Button x:Name="PART_Edit" Width="20" Height="20" Content="{DynamicResource dPen}" Style="{DynamicResource dTranspButton}" Click="btnEdit_Click"/> 
    <Button x:Name="PART_Delete" Width="20" Height="20" Content="{DynamicResource dCross}" Style="{DynamicResource dTranspButton}" Click="btnDelete_Click"/> 
</WrapPanel>
<Label Content="{TemplateBinding Content}"  Margin="2,0,45,0" Padding="0,0,0,0" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>

dCB_Props の xaml の一部:

<ComboBox HorizontalContentAlignment="Stretch" x:Name="PART_cb" Background="Transparent" Margin="0,0,0.367,0" d:LayoutOverrides="HorizontalAlignment" ItemsSource="{Binding Items, ElementName=dcb}" IsDropDownOpen="{Binding IsDropDownOpen,ElementName=dcb, Mode=TwoWay}" Grid.ColumnSpan="3" Style="{DynamicResource DaisyComboBox}" />
<Button x:Name="PART_Edit" Width="20" Height="20" Content="{DynamicResource dPen}" Visibility="Hidden" Style="{DynamicResource dTranspButton}" Margin="2.581,1.48,17.778,-1.48" Grid.Column="1" Click="btnEdit_Click"/>
<Button x:Name="PART_Delete" Width="20" Height="20" Content="{DynamicResource dCross}" Visibility="Hidden" Margin="22.602,1.48,-2.243,-1.48" Style="{DynamicResource dTranspButton}" Grid.Column="1" Click="btnDelete_Click"/>
<Button x:Name="PART_Add" Content="+" Grid.Column="3" Margin="0,0,0,0" Style="{DynamicResource dTranspButton}" Click="btnAdd_Click"/>

上記の 2 つはオブジェクトのコードであることに注意してください。列の定義、イベント トリガーなどは省略しています。

dCB_Props.xaml.cs コードの一部は次のとおりです。

public partial class dCB_Props : UserControl
{
    public dCB_Props()
    {
        this.InitializeComponent();
        Items= new ObservableCollection<object>();
        Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged);
    }

    void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            foreach (var o in e.NewItems)
            {
                if (o.GetType() == typeof(EditDeleteItem))
                {
                    EditDeleteItem itm = (EditDeleteItem)o;
                    itm.EditClick += new RoutedEventHandler(ItemEdit_Click);
                    itm.DeleteClick += new RoutedEventHandler(ItemDelete_Click);
                }
            }
        }
    }
  ...//I've left some code here since I don't deem it's that important for the situation
    private void ItemEdit_Click(object sender, RoutedEventArgs e)
    {
        DependencyObject d = GetTemplateChild("PART_cb");
        if (d == null) return;
        ComboBox cb = (ComboBox)d;
        if (cb.SelectedItem != null) RaiseEvent(new RoutedEventArgs(EditClickEvent, e.OriginalSource));
    }
}

タイプの項目を追加し、内部にある LabelEditDeleteItemのプロパティを削除すると、上記は機能します。以下に示す ItemTemplate をの ContentTemplate に設定した場合にも機能します。ただし、前述のように、異なるデータ テンプレートを使用する必要があるため、すべてのデータ テンプレートをリソース ディクショナリに配置する必要があり、テンプレート セレクターを使用する必要があると想定しています。ItemTemplatedCB_PropsEditDeleteItem

データ テンプレート:

<DataTemplate x:Shared="false" x:Key="TagTemplate">
        <local:EditDeleteItem x:Name="edItem">
            <local:EditDeleteItem.Content>
                <StackPanel>
                    <TextBlock Text="{Binding Path=Content.Label}"/>
                    <CheckBox Content="Isolated" IsChecked="{Binding Content.IsIsolated}"/>
                    <CheckBox Content="Match Case" IsChecked="{Binding Content.MatchCase}"/>
                    <CheckBox Content="Include" IsChecked="{Binding Content.Include}"/>
                </StackPanel>
            </local:EditDeleteItem.Content>
        </local:EditDeleteItem>
</DataTemplate> 

コマンドバインディングを使用する必要があると思います。しかし、CommandBindings をどこに配置すればよいか、またどのように使用すればよいかはよくわかりませんが、1、2 ページ読んだことがあります。

ありがとう、ハッサン

4

1 に答える 1

0

ItemTemplateが使用されている場合、Items_CollectionChangedのサブスクリプションは発生しないため、イベントは発生しますが、キャッチしません。

ItemsControl(およびComboBox)がItemsSourceとどのように連携するかを理解する必要があります。ItemsControlは、ItemContainerGeneratorを使用してビジュアルツリーにデータを入力します。ItemsSourceの各アイテムは、ContentControlから派生したコンテナーにラップされます。次に、itemがContentとして設定され、ItemTemplateがContentTemplateとして設定されます。EditDeleteItemをItemTemplateに配置すると、ビジュアルツリーの一部になりますが、アイテムにはなりません。そのため、e.NewItemsにはEditDeleteItemがなく、サブスクリプションもありません。

あなたが言ったように、正しい方法はコマンドです。次の2つのコマンドを宣言する必要があります。

public class EditDeleteItem : UserControl
{
    ...
    public static readonly RoutedUICommand EditCommand = new RoutedUICommand(...);
    public static readonly RoutedUICommand DeleteCommand = new RoutedUICommand(...);
    ...
}

これで、テンプレートの一部は次のようになります。

<WrapPanel ...>
    <Button ... Command="{x:Static EditDeleteItem.EditCommand}"/>
    <Button ... Command="{x:Static EditDeleteItem.DeleteCommand}"/>
</WrapPanel>

次に、コマンドバインディングをdCB_Propsに追加します。

public partial class dCB_Props : UserControl
{
    static dCB_Props()
    {
        ...
        CommandManager.RegisterClassCommandBinding(
            typeof(dCB_Props),
            new CommandBinding(EditDeleteItem.EditCommand, OnEditCommandExecuted));
        CommandManager.RegisterClassCommandBinding(
            typeof(dCB_Props),
            new CommandBinding(EditDeleteItem.DeleteCommand, OnDeleteCommandExecuted));
        ...
    }
    ...
}

EditDeleteItemからの対応するコマンドを処理するには、OnEditCommandExecutedとOnDeleteCommandExecutedを実装する必要があります。

私はあなたの質問を正しく理解したと思います;)

于 2012-04-15T18:08:59.720 に答える