1

オブジェクトのコレクションを持つ ItemsControl があります。オブジェクトをクリックして、詳細情報を含むパネルを取得したくありません。

そこで、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 はコード ビハインドで定義されています。

4

2 に答える 2

4

変化する

<Button>

に...

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

この ItemsControl の項目として使用するクラスで、使用するボタンの ICommand を返す読み取り専用プロパティを実装します。

編集:

この例では、 http://msdn.microsoft.com/en-us/magazine/dd419663.aspxRelayCommandで入手できるという ICommand の実装を利用しました。C#の完全なクラスについては、その記事の図 3 を参照してください。使用するために Visual Basic に変換しました。そのコードは以下のとおりです。これは、WPF システムへのコマンドの登録を自動化するだけであり、便利なコンストラクターを提供します。RelayCommand

''' <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読み取り専用プロパティとして を公開し、RelayCommand を格納するためのバッキング フィールドを使用します。これは ICommand を実装することを忘れないでください。切り捨てられたサンプルを次に示します。

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

「OnClick」名は必須ではありません。このシステムは、VB6 のイベント ハンドラーのように規約に基づいていないため、コマンドには任意の名前を付けることができます。

これを行う方法は複数あります。ICommand の "Caliburn.Micro" 実装に興味をそそられます。これ慣習に基づいており、スタイルによっては読みやすくなる可能性があります。しかし、Caliburn は、非常に有能で資格のある愛好家ではありますが、愛好家によるオープンソースの取り組みです。詳細については、Google または Bing の「Caliburn.Micro」を参照してください。

于 2010-07-19T15:44:48.510 に答える
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>

テンプレートのこの種のメカニズムにより、定義を配置する場所に応じて、ボタンのプロパティ、および場合によってはビジュアル ツリーの他の部分のプロパティを制御できます。

また、物事を少し異なる方法で設計することを検討することもできます。すべての定義をまったく同じ方法でスタイルに積み上げる必要はありません。

于 2010-07-21T15:32:50.370 に答える