2012-04-14 6 views
0

Ich habe eine Benutzerkontrolle, genannt dCB_Props, die mehrere Objekte enthält, am wichtigsten eine ComboBox, die an eine Observable Collection gebunden ist. Obwohl die Auflistung jedes Objekt aufnehmen kann, wird normalerweise ein UserControl namens EditDeleteItem benötigt. Ich habe dCB_Props eingestellt, um EditDeleteItem als ItemsTemplate zu verwenden, aber die Ereignisse werden nicht ausgelöst. Wenn ich andererseits eine Instanz von EditDeleteItem anschließe, werden die Ereignisse ausgelöst. Ich kann Elemente auf diese Weise nicht hinzufügen, da EditDeleteItem andere Steuerelemente hostet und ich verschiedene DataTemplates verwenden muss.Wie kann ich ein benutzerdefiniertes Routed-Ereignis von einem DataTemplate auslösen?

EditDeleteItem hat zwei Routed-Ereignisse namens EditClick und DeleteClick.

Wenn sich die Sammlung ändert, wird ein Ereignis ausgelöst, das prüft, ob das hinzugefügte Element vom Typ EditDeleteItem ist. Wenn dies der Fall ist, fügt es den beiden oben genannten Ereignissen Handler hinzu.

Ein Teil der XAML für EditDeleteClick:

<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"/> 

Ein Teil der XAML für dCB_Props:

<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"/> 

Beachten Sie die beiden oben genannten Codes nur für Objekte, ich habe Spaltendefinitionen weggelassen, Ereignisauslöser, usw.

Teil dCB_Props.xaml.cs Code ist:

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)); 
    } 
} 

Das obige funktioniert, wenn ich ein Element vom Typ EditDeleteItem hinzufügen und die ItemTemplate Eigenschaft für das Label entfernen, das sich in dCB_Props befindet. Es funktioniert auch, wenn ich das ItemTemplate, das unten gezeigt wird, in EditDeleteItem's ContentTemplate einstelle. Aber wie bereits erwähnt, muss ich verschiedene Datenvorlagen verwenden. Ich gehe daher davon aus, dass alle Datenvorlagen in einem Ressourcenwörterbuch gespeichert sein müssen, und dann muss ich eine Vorlagenauswahl verwenden.

Datenvorlage:

<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> 

Ich glaube, ich brauche Befehl Bindungen zu verwenden. Aber ich bin mir nicht sicher, wo ich die CommandBindings platzieren soll, und ich bin mir nicht sicher, wie ich sie benutzen soll, obwohl ich ein oder zwei Seiten gelesen habe.

Danke, Hassan

Antwort

0

Die Ereignisse werden gefeuert, aber Sie sie nicht fangen, weil Abonnement in Items_CollectionChanged nie auftritt, wenn ItemTemplate verwendet wird.

Sie sollten verstehen, wie ItemsControl (und ComboBox) mit ItemsSource funktioniert. ItemsControl verwendet ItemContainerGenerator, um seine visuelle Struktur zu füllen. Jedes Element aus ItemsSource wird in einen Container umgeleitet, der von ContentControl abgeleitet wurde. Dann wird der Artikel als Inhalt festgelegt, ItemTemplate wird als ContentTemplate usw. festgelegt. Wenn Sie EditDeleteItem in ItemTemplate einfügen, wird es ein Teil der visuellen Struktur, aber kein Element. Aus diesem Grund gibt es kein EditDeleteItem in e.NewItems und kein Abonnement.

Der richtige Weg ist Befehle, wie Sie erwähnt haben.Sie sollten zwei Befehle erklären:

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

nun der Teil der Vorlage aussehen kann:

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

Sie dann Befehl Bindungen dCB_Props hinzufügen:

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)); 
     ... 
    } 
    ... 
} 

Sie müssen OnEditCommandExecuted implementieren und OnDeleteCommandExecuted, um die entsprechenden Befehle von EditDeleteItem zu behandeln.

Ich hoffe, ich habe Ihre Frage richtig verstanden;)

Verwandte Themen