繁体   English   中英

在自定义控件中处理来自DataTemplate的事件

[英]Handle events from DataTemplate in custom control

我正在编写一个WPF客户端,并创建了一个将在客户端中使用的自定义聊天控件,聊天控件包含一个ChatClient,用于处理加入和离开聊天服务,并按照以下XAML显示已连接用户的列表:

<Style TargetType="{x:Type chat:ChatClient}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type chat:ChatClient}">
                <Grid Margin="0,0,0,0" Background="{StaticResource ChatClientBackgroundBrush}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="135" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid Grid.Row="0" Margin="0,0,0,0" Background="{StaticResource ChatClientBackgroundBrush}">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="100" />
                            <RowDefinition Height="32" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <Border Grid.Column="0" Grid.Row="0" Height="100" Margin="0,0,0,0" Padding="1,1,1,0" BorderBrush="{StaticResource ChatClientAvatarBorderBrush}">
                            <Image Height="80" Width="80" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                <Image.Clip>
                                    <EllipseGeometry Center="40,40" RadiusX="40" RadiusY="40" />
                                </Image.Clip>
                            </Image>
                        </Border>
                        <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
                            <Ellipse Height="8" Width="8" Fill="{StaticResource ChatClientPresenceOnlineBrush}" Margin="6,-8,0,0" />
                            <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CurrentPerson.Name}" Margin="8,0" Foreground="{StaticResource ChatClientTextBrush}"
                                       FontSize="16" />
                        </StackPanel>
                    </Grid>

                    <Border Grid.Row="1" BorderThickness="0,1,0,0" BorderBrush="{StaticResource ChatClientBorderBrush}">
                        <Grid Background="{StaticResource ChatClientBackgroundBrush}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" MinHeight="100" />
                            </Grid.RowDefinitions>
                            <ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
                                <StackPanel>
                                    <ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
                                        <ItemsControl.ItemTemplate>
                                            <DataTemplate>
                                                <ContentControl>
                                                    <Border Style="{StaticResource IsMouseOver}">
                                                        <Grid>
                                                            <Grid.ColumnDefinitions>
                                                                <ColumnDefinition Width="40" />
                                                                <ColumnDefinition Width="*" />
                                                            </Grid.ColumnDefinitions>
                                                            <Grid.RowDefinitions>
                                                                <RowDefinition Height="*" />
                                                                <RowDefinition Height="*" />
                                                            </Grid.RowDefinitions>
                                                            <Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0"
                                                                BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
                                                                <Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                                                    <Image.Clip>
                                                                        <EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
                                                                    </Image.Clip>
                                                                </Image>
                                                            </Border>
                                                            <TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold"
                                                                   Text="{Binding Name}"></TextBlock>
                                                        </Grid>
                                                    </Border>
                                                </ContentControl>
                                            </DataTemplate>
                                        </ItemsControl.ItemTemplate>
                                    </ItemsControl>
                                </StackPanel>
                            </ScrollViewer>
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这在Chat程序集的ResourceDictionary中定义,ChatClient作为控件添加到主应用程序窗口。

这一切都很棒,当我运行应用程序时,它连接到聊天服务器,我在主窗口右侧有一个很好的面板,其中包含已连接用户的列表。

好的,所以我的问题与上面的XAML中的以下部分有关:

<ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
    <StackPanel>
        <ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentControl>
                        <Border Style="{StaticResource IsMouseOver}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="40" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0" BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
                                    <Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                        <Image.Clip>
                                            <EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
                                        </Image.Clip>
                                    </Image>
                                </Border>
                                <TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold" Text="{Binding Name}"></TextBlock>
                            </Grid>
                        </Border>
                    </ContentControl>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

在上面的DataTemplate中,为每个连接的Person创建了一个项目,我想知道如何从ChatClient处理ContentControl的MouseDoubleClick事件,以便ChatClient将负责创建ChatWindow,示例仍然很好对WPF来说很新鲜。

我一直在阅读Attached Behaviors,但很难理解它们如何适应我想要实现的目标,即我的ChatClient类有一个事件处理程序,当我双击DataTemplate中添加的任何项目时会触发该事件处理程序。

任何有关如何实现这一目标的建议都将受到极大欢迎。

我建议你在MouseDoubleClick事件上触发一个Command

要将MouseDoubleClick事件连接到Command并将ClientId传递给它,您可以使用这样的东西:

<ScrollViewer x:Name="srcContacts" Grid.Row="0" Margin="0,0,0,0" VerticalScrollBarVisibility="Auto">
    <StackPanel>
        <ItemsControl ItemsSource="{Binding Path=People, RelativeSource={RelativeSource AncestorType={x:Type chat:ChatClient}}}" x:Name="Contacts">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentControl>

                         <!-- ــــInputBinding For Mouse LeftDoubleClickــــ -->
                         <ContentControl.InputBindings>
                              <MouseBinding Gesture="LeftDoubleClick"
                                            Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ClientDoubleClickCommand}" 
                                            CommandParameter="{Binding ClientId}"/>
                         <ContentControl.InputBindings>
                         <!-- ــــــــــــــــــــــــــــــــــــــــ -->

                        <Border Style="{StaticResource IsMouseOver}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="40" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Height="35" Width="35" Margin="5,0,0,0" BorderBrush="{StaticResource ChatClientPresenceOnlineBrush}" BorderThickness="2" CornerRadius="15">
                                    <Image Height="30" Width="30" Source="Cleo.Windows.Ui.Chat;component/Resources/noavatar.png" StretchDirection="Both" Stretch="Fill">
                                        <Image.Clip>
                                            <EllipseGeometry Center="15,15" RadiusX="15" RadiusY="15" />
                                        </Image.Clip>
                                    </Image>
                                </Border>
                                <TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource ChatClientTextBrush}" Padding="0" Margin="10,0,0,0" FontWeight="Bold" Text="{Binding Name}"></TextBlock>
                            </Grid>
                        </Border>
                    </ContentControl>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

然后你可以简单地在ClientChat类中定义ClientDoubleClickCommand command (就像People其他成员一样):

public class ChatClient: INotifyPropertyChanged
{
    //-------- Peopole property --------
    .
    .
    .

    //-------- ClientDoubleClickCommand --------
    ICommand clientDoubleClickCommand;
    public ICommand ClientDoubleClickCommand
    {
        get
        {
            return clientDoubleClickCommand ??
                (clientDoubleClickCommand = new MyCommand(DoThisOnDoubleClick, true));
        }
    }

    private void DoThisOnDoubleClick(object clientId)
    {
        // Write your target codes (on Mouse Left Double Click) here:
        throw new NotImplementedException();
    }

    //-------- OTHER PROPERTIES AND CODES OF CLASS--------
    .
    .
    .

}

// MyCommand Class: This class is a technique to implement commands easily
public class MyCommand: ICommand
{
    private readonly Action<object> _action;
    private readonly bool _canExecute;
    public MyCommand(Action<object> action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }
}

public class People: INotifyPropertyChanged
{
   // ClientId Property:
    .
    .
    .

   // ClientName Property:
    .
    .
    .

   //-------- OTHER PROPERTIES AND CODES OF CLASS--------
    .
    .
    .

}

在此示例中,我假设您在People类中具有ClientId属性以保留每个客户端的ID。

现在你有一个People属性,它是一个客户列表,你用它像这样:

<ItemsControl ItemsSource="{Binding Path=People,........

另一方面, 如果 ItemsControl DataContext是»» ChatClient类, 那么我们可以访问其中的ClientDoubleClickCommand ,并在ItemsControl块内的以下行中访问People类中的ClientId (通过ItemsSource ):

<MouseBinding Gesture="LeftDoubleClick"
              Command="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ClientDoubleClickCommand}" 
              CommandParameter="{Binding ClientId}"/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM