2010-07-19 5 views
1

개체 컬렉션이있는 ItemsControl이 있습니다. 개체를 클릭 한 다음 자세한 정보가있는 패널을 가져올 수 없게되었습니다.WPF : 단추를 DataTemplate으로 사용하여 클릭 이벤트를 추가하는 방법

그래서 ItemsControl의 항목에 대해 DataTemplate의 스타일을 단추로 지정하기 때문에 문제가없는 것 같습니다. 그러나 스타일에이 버튼의 클릭 이벤트를 설정하는 방법에 대해서는 잘 모릅니다. 그것은 EventSetter를 사용해야한다고 말하지만 작동하도록 설정할 수는 없습니다.

<Style TargetType="Expander" > 
      <Style.Resources> 
       <Style TargetType="ItemsControl" > 
        <Setter Property="Template" > 
         <Setter.Value> 
          <ControlTemplate TargetType="ItemsControl"> 
           <Border BorderThickness="0,1,0,1" BorderBrush="{StaticResource DarkColorBrush}" > 
            <ScrollViewer Margin="0" VerticalScrollBarVisibility="Auto" 
                Focusable="false"> 
             <StackPanel Margin="2" IsItemsHost="True" /> 
            </ScrollViewer> 
           </Border> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
        <Setter Property="ItemTemplate" > 
         <Setter.Value> 
          <DataTemplate DataType="{x:Type data:CompanyViewModel}" > 
           <Button> 
            <Button.Resources> 
             <Style TargetType="Button"> 
              <Setter Property="Template"> 
               <Setter.Value> 
                <ControlTemplate TargetType="Button"> 
                 <Border Name="Bd" BorderBrush="{StaticResource DarkColorBrush}" 
                   BorderThickness="1" 
                   Margin="5" 
                   CornerRadius="8"> 

                  <Border.Background> 
                   <!-- Removed for brevity --> 
                  </Border.Background> 

                  <StackPanel Orientation="Vertical"> 
                   <TextBlock Margin="5" Text="{Binding Path=Name}" Style="{StaticResource MenuText}" FontSize="16" HorizontalAlignment="Center" /> 
                   <TextBlock Margin="5,0,5,5" Text="{Binding Path=Code, StringFormat=Kt. {0}}" Style="{StaticResource MenuText}" HorizontalAlignment="Center" /> 
                  </StackPanel> 
                 </Border> 

                 <ControlTemplate.Triggers> 
                  <Trigger Property="IsMouseOver" Value="true"> 
                   <Setter TargetName="Bd" Property="Background"> 
                    <Setter.Value> 
                     <!-- Removed for brevity --> 
                    </Setter.Value> 
                   </Setter> 
                  </Trigger> 
                  <Trigger Property="Button.IsPressed" Value="true"> 
                   <Setter TargetName="Bd" Property="Background"> 
                    <Setter.Value> 
                     <!-- Removed for brevity --> 
                    </Setter.Value> 
                   </Setter> 
                  </Trigger> 
                 </ControlTemplate.Triggers> 
                </ControlTemplate> 
               </Setter.Value> 
              </Setter> 
             </Style> 
            </Button.Resources> 
           </Button> 
          </DataTemplate> 
         </Setter.Value> 
        </Setter> 
       </Style> 
      </Style.Resources> 
      <Setter Property="Template" > 
       <Setter.Value> 
        <ControlTemplate TargetType="Expander"> 
         <Grid> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="*" /> 
           <ColumnDefinition Width="30" /> 
          </Grid.ColumnDefinitions> 
          <ToggleButton Grid.Column="1" 
              IsChecked="{Binding Path=IsExpanded,Mode=TwoWay, 
              RelativeSource={RelativeSource TemplatedParent}}" /> 
          <ContentPresenter Name="Content" Grid.Column="0" /> 
         </Grid> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsExpanded" Value="false"> 
           <Setter TargetName="Content" Property="Visibility" Value="Collapsed" /> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

내가 버튼 클릭으로 달성하기 위해 원하는 것을 추가하기로 결정 :

<Button Click="CompanyClick" /> 

CompanyClick 뒤에 코드에서 정의되는 다음

는 코드입니다.

+0

"

답변

2

또한이있다 :

<ControlTemplate.Triggers> 
    <EventTrigger RoutedEvent="Button.Click"> 
     <BeginStoryboard> 
      <Storyboard> 
<!-- Animations manipulating the button here --> 
      </Storyboard> 
     </BeginStoryboard> 
    </EventTrigger> 
<!-- The rest of your triggers here --> 
</ControlTemplate.Triggers> 

이 템플릿 메커니즘 이런 종류의 버튼의 속성을 제어 할 수 있습니다, 그리고 것입니다 당신이를 넣어 위치에 따라 시각적 트리의 다른 부분에서 가능 속성 definiton.

아키텍처를 약간 다르게 고려할 수도 있습니다.필자는 모든 정의를 꼭 같은 방식으로 스타일에 집어 넣지는 않을 것입니다.

+0

실제로 EventSetter를 사용하여 시도했지만 어떤 이유로 컴파일되지 않았습니다. 그런 다음 Button 스타일로 EventSetter를 설정하고 다른 스타일을 기본으로 설정했는데 제대로 작동했습니다. –

4

변경

<Button> 

으로 ...이 ItemsControl에의 항목으로 사용할 클래스에

<Button Command="{Binding OnClick}" /> 

은, 사용하는 버튼에 대한 ICommand의를 반환하는 읽기 전용 속성을 구현 .

편집

:이 예를 들어

, 나는 ICommand의의 구현의 사용 http://msdn.microsoft.com/en-us/magazine/dd419663.aspx에서 확인할 수있다 RelayCommand를 호출했다. C#의 전체 RelayCommand 클래스에 대한 해당 기사의 그림 3을 참조하십시오. 나는 그것을 사용하기 위해 Visual Basic으로 변환했다. 그 코드는 아래에있다. 그것은 WPF 시스템 명령의 등록을 자동화하는 것보다 아무것도 더하지, 편리한 생성자를 제공합니다 : 클래스를 사용

''' <summary> 
''' Implements the ICommand interface 
''' </summary> 
''' <remarks> 
''' Thanks to Josh Smith for this code: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 
''' </remarks> 
Public Class RelayCommand 
    Implements ICommand 
#Region "Fields" 

    Private ReadOnly _execute As Action(Of Object) 
    Private ReadOnly _canExecute As Predicate(Of Object) 

#End Region ' Fields 

#Region "Constructors" 

    Public Sub New(ByVal execute As Action(Of Object)) 
     Me.New(execute, Nothing) 
    End Sub 

    Public Sub New(ByVal execute As Action(Of Object), ByVal canExecute As Predicate(Of Object)) 
     If execute Is Nothing Then 
      Throw New ArgumentNullException("execute") 
     End If 

     _execute = execute 
     _canExecute = canExecute 
    End Sub 
#End Region ' Constructors 

#Region "ICommand Members" 

    <DebuggerStepThrough()> 
    Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute 
     Return If(_canExecute Is Nothing, True, _canExecute(parameter)) 
    End Function 

    Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged 
     AddHandler(ByVal value As EventHandler) 
      AddHandler CommandManager.RequerySuggested, value 
     End AddHandler 
     RemoveHandler(ByVal value As EventHandler) 
      RemoveHandler CommandManager.RequerySuggested, value 
     End RemoveHandler 
     RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs) 
      CommandManager.InvalidateRequerySuggested() 
     End RaiseEvent 
    End Event 

    Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute 
     _execute(parameter) 
    End Sub 

#End Region ' ICommand Members 
End Class 

, 당신은 다음과 같은 ICommand를 노출하여, 당신의 ViewModel에 ICommand의를 구현할 수 있습니다 이 클래스의 읽기 전용 속성과 ICommand를 구현하는 것을 잊지 말아야하는 RelayCommand를 저장하는 백킹 필드가 있습니다. 여기에 절단 된 샘플의 다음 "의 OnClick"이름 하지 필요하다

Public Class CompanyViewModel 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 

    Private _OnClick As RelayCommand 
    Public ReadOnly Property OnClick As ICommand 
     Get 
      If _OnClick Is Nothing Then 
       _OnClick = New RelayCommand(Sub() 
               Me.OnClickExecute() 
              End Sub, 
              Function() 
               Return Me.OnClickCanExecute() 
              End Function) 
      End If 
      Return _OnClick 
     End Get 
    End Property 
    Private Function OnClickCanExecute() As Boolean 
     ' put a test here to tell the system whether conditions are right to execute your command. 
     ' OR, just return True and it will always execute the command. 
    End Function 

    Private Sub OnClickExecute() 
     ' put the processing for your command here; THIS IS YOUR EVENT HANDLER 
    End Sub 
    ' .... implement the rest of your ViewModel 
End Class 

는; VB6가 이벤트 핸들러와 동일한 방식으로 시스템이 관례에 기반하지 않기 때문에 명령에 이름을 지정할 수 있습니다.

이렇게하는 방법은 여러 가지가 있습니다. 저는 ICommand의 "Caliburn.Micro"구현에 흥미가 있습니다. 은 컨벤션 기반의이며 스타일에 따라 상황을 더 쉽게 읽을 수 있습니다. 그러나 Caliburn은 매우 유능하고 자격있는 매니아 임에도 불구하고 열광적 인 노력에 의한 오픈 소스입니다. 자세한 내용은 Google 또는 Bing "Caliburn.Micro"를 참조하십시오.

+0

글쎄, itemscontrol을 포함하는 클래스 안에서 일어나는 간단한 이벤트 핸들링을하고있다. 이 ICommand를 계속 사용해야하나요? 버튼을 사용하여 포함하는 클래스에서 메서드 (이벤트 핸들러)를 활성화시키는 방법에 대해 조금 힌트를 주시겠습니까? 또한 OnClick 메서드가 작동하도록 이름을 지정해야합니까? –

+0

더 완벽한 예를 만들고 대답을 편집 할 것입니다. –

+0

잘 알았다면 이벤트 처리가 회사 클래스에 있습니다. itesmControl이 포함 된 클래스 내부에 있어야합니다. 다른 객체와 관련이 있기 때문입니다. Click = CompanyClick과 같은 간단한 명령으로 버튼을 정의 할 수 있다는 것이 이상하다는 것을 알았지 만 ControlTEmplate에 들어가면 더 이상 할 수 없습니다. –

관련 문제