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