首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WPF:使用按钮作为DataTemplate,如何添加单击事件

WPF:使用按钮作为DataTemplate,如何添加单击事件
EN

Stack Overflow用户
提问于 2010-07-19 23:26:15
回答 2查看 14.1K关注 0票数 1

我有一个包含对象集合的ItemsControl。我不希望能够点击对象,然后得到一个面板与更多的信息。

因此,我决定将ItemsControl中项目的DataTemplate样式化为按钮,这似乎可以很好地工作。但是,我不知道如何在样式中设置此按钮的单击事件。它说我应该使用EventSetter,但是我不能让它工作。

代码如下:

代码语言:javascript
运行
复制
  <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>

我决定添加我想要通过单击按钮来完成的功能:

代码语言:javascript
运行
复制
<Button Click="CompanyClick" />

在后台代码中定义的CompanyClick。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-07-21 23:32:50

还有这个:

代码语言:javascript
运行
复制
<ControlTemplate.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
        <BeginStoryboard>
            <Storyboard>
<!-- Animations manipulating the button here -->
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
<!-- The rest of your triggers here -->
</ControlTemplate.Triggers>

模板中的这种机制将使您能够控制按钮的属性,并可能控制可视化树的其他部分中的属性,这取决于您将定义放在哪里。

您可能还会考虑以不同的方式设计一些东西。我不一定会以完全相同的方式将所有的定义堆积到样式中。

票数 2
EN

Stack Overflow用户

发布于 2010-07-19 23:44:49

变化

代码语言:javascript
运行
复制
<Button>

为了..。

代码语言:javascript
运行
复制
<Button Command="{Binding OnClick}" />

在用作此ItemsControl中的项的类上,实现一个只读属性,该属性为要使用的按钮返回一个ICommand。

编辑:

在本例中,我使用了一个名为RelayCommand的ICommand实现,它可以在http://msdn.microsoft.com/en-us/magazine/dd419663.aspx上找到。有关C#中的完整RelayCommand类,请参阅该文章的图3。我将其转换为Visual Basic供我使用,代码如下。它所做的仅仅是在WPF系统中自动注册命令,并为您提供一个方便的构造函数:

代码语言:javascript
运行
复制
''' <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

使用该类,您可以在ViewModel上实现ICommand,方法是在该类中将ICommand公开为只读属性,并提供一个用于存储RelayCommand的后备字段,别忘了,该字段实现了ICommand。下面是一个截断的示例:

代码语言:javascript
运行
复制
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是一个爱好者的开源努力,尽管他是一个非常有能力和合格的爱好者。谷歌或必应搜索"Caliburn.Micro“获取更多信息。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3282441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档