2015-12-29 4 views
3

Я пишу WPF-клиент и создал пользовательский элемент управления чата, который будет использоваться внутри клиента, элемент управления чатом состоит из ChatClient, который обрабатывает соединение и выход из службы чата и отображение списка подключенных пользователей в соответствии со следующим: XAMLОбработка событий из DataTemplate в настраиваемом элементе управления

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

Это определено в 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 элемент создается для каждого подключенного человека, я хотел бы знать, как я могу справиться событие MouseDoubleClick из ContentControl из ChatClient, так что ChatClient будет отвечать за создание ChatWindow, примеры были бы хорошими, как еще совершенно новые для WPF.

Я читал «Приложенные поведенья», но пытался понять, как это будет соответствовать тому, что я ищу, чтобы добиться того, что у моего класса ChatClient есть обработчик событий, который запускается при двойном щелчке по любому элементу, добавленному в DataTemplate.

Любые предложения о том, как достичь этого, будут получены в значительной степени.

ответ

1

Я рекомендую пожар Command на мероприятии MouseDoubleClick.

Для подключения 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> 

Тогда вы можете просто определить ClientDoubleClickCommandcommand в ClientChat классе (как и другие члены ней, такие как 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-------- 
    . 
    . 
    . 

} 

В этом примере, я предположил, что вы едите ClientId свойства в ваших People класс для хранения идентификатора каждого клиента.

Теперь у вас есть People собственности, это список клиентов, и вы использовали его, как это:

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

С другой стороны еслиItemsControlDataContext быть »» ChatClient класса затем у нас есть доступ к ClientDoubleClickCommand и его доступ к ClientId в категории People (по ItemsSource) в следующей строке внутри ItemsControl блок:

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

Не могли бы вы подробнее рассказать о своем ответе, как связать элемент управления ChatClient с событием или командой? Я использую ScrollViewer, у которого нет элемента ItemsControl, как ваше решение соответствует этому? Не могли бы вы объяснить 'DataContext.ClientDoubleClickCommand' более понятно? –

+0

@Neil, я отредактировал ответ и объяснил вам больше. Я рекомендую вам использовать прозрачный шаблон MVVM в вашем проекте. – RAM

+0

Это потрясающе, спасибо, что это работает шарм, я никогда не перестаю удивляться силе WPF, когда я сталкиваюсь с такими вещами. Мне пришлось внести незначительные изменения в привязку 'Command', так как мой' ItemsControl' был '

Смежные вопросы