2012-04-14 2 views
0

나는 여러 개의 개체를 포함하는 dCB_Props이라는 사용자 정의 컨트롤이 있는데, 가장 중요한 것은 Observable Collection에 바인딩 된 ComboBox입니다. 컬렉션은 개체를 사용할 수 있지만 일반적으로 이라는 UserControl을 사용합니다. dCB_PropsEditDeleteItem으로 설정하고 ItemsTemplate으로 설정했지만 이벤트가 실행되지 않습니다. 반면에 EditDeleteItem의 인스턴스를 추가하면 이벤트가 실행됩니다. EditDeleteItem이 다른 컨트롤을 호스팅하고 다른 DataTemplates를 사용해야하므로이 방법으로 항목을 추가 할 수 없습니다.DataTemplate에서 사용자 지정 라우팅 이벤트를 발생시키는 방법은 무엇입니까?

EditDeleteItem에는 EditClickDeleteClick이라는 두 개의 라우팅 된 이벤트가 있습니다.

컬렉션이 변경되면 추가 된 항목이 EditDeleteItem인지 확인하는 이벤트가 발생합니다. 그렇다면 위에서 언급 한 두 가지 이벤트에 핸들러를 추가합니다. EditDeleteClick에 대한 XAML의

부 : dCB_Props에 대한 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"/> 

부 : 위의 두 그냥 객체에 대한 코드입니다

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

주, 나는 열 정의를 남겨 두었다 이벤트 트리거 등 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)); 
    } 
} 

EditDeleteItem 유형의 항목을 추가하고 dCB_Props 안에있는 레이블에 대해 ItemTemplate 속성을 제거하면 위의 코드가 작동합니다. 아래에 표시된 ItemTemplate을 EditDeleteItem의 ContentTemplate에 설정하면 작동합니다. 그러나 언급 한 바와 같이 다른 데이터 템플릿을 사용해야하므로 모든 데이터 템플릿이 리소스 사전에 있어야하며 템플릿 선택기를 사용해야합니다.

데이터 템플릿 :

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

내가 명령 바인딩을 사용해야 믿습니다. 그러나 CommandBinding을 어디에 둘 것인지, 그리고 페이지 나 2를 읽었을 지 모르지만 어떻게 사용하는지 잘 모르겠습니다.

덕분에, 하산

답변

0

이 이벤트는 해고,하지만 ItemTemplate을 사용하는 경우 Items_CollectionChanged에 가입이 결코 발생하지 않기 때문에 당신은 그들을 잡을 수 없습니다.

ItemsControl (및 ComboBox)이 ItemsSource와 작동하는 방식을 이해해야합니다. ItemsControl은 ItemContainerGenerator를 사용하여 시각적 트리를 채 웁니다. ItemsSource의 각 항목은 ContentControl에서 파생 된 컨테이너로 래핑됩니다. 그런 다음 항목이 Content로 설정되고 ItemTemplate이 ContentTemplate로 설정됩니다. EditDeleteItem을 ItemTemplate에 넣으면 비주얼 트리의 일부가되지만 항목은 아닙니다. 그래서 e.NewItems에는 EditDeleteItem이없고 subscription이 없습니다.

올바른 방법은 언급 한대로 명령입니다.

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

당신은 OnEditCommandExecuted를 구현해야하고 그런 다음 당신이 dCB_Props에 명령 바인딩을 추가

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

:처럼 이제 템플릿의 일부가 보일 수 있습니다

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

: 당신은 두 명령을 선언해야 EditDeleteItem에서 해당 명령을 처리하기 위해 OnDeleteCommandExecuted. 내가 제대로 질문을 이해 바랍니다

)

관련 문제