2014-07-22 27 views
5

Używam ItemsControl do przechowywania mojej kolekcji. ItemsPanel jest Canvas The ItemTemplate jest blok Border>StackPanel>TextBlocks Chcę powiązać polecenie w DataTemplate złapać kliknij na bloku (pozycja z mojej kolekcji)Wiązanie polecenia WPF w DataTemplate

Kod:

<Grid Grid.Row="1" Grid.Column="1" > 
     <ItemsControl ItemsSource="{Binding Products}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <helpers:DragCanvas 
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Stretch" 
         AllowDragging="True" 
         AllowDragOutOfView="False" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <!-- The border and its content is what I see 
        on my canvas, I want to bind a command here (on click do something) --> 
        <Border BorderThickness="1" BorderBrush="Gold"> 
         <StackPanel Orientation="Horizontal"> 
          <TextBlock Text="{Binding Path=Name}" /> 
          <TextBlock Text="{Binding Path=Price}" /> 
         </StackPanel> 
        </Border> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate>  
     </ItemsControl> 
    </Grid> 

Odpowiedz

10

pierwszym obiektem, który przychodzi na uwadze, należy dołączyć do polecenia jest Border a ponieważ ten ostatni nie posiada zdarzenie Click, będę użycie MouseLeftButtonDown, a od polecenia są wykorzystywane tylko dowcip h Button -base kontrole (Button, RadioButton, CheckBox, RepeatButton ...) będzie potrzeby EventTriggers Twój DataTemplate powinna wyglądać następująco:

<DataTemplate> 
     <Border BorderThickness="1" BorderBrush="Gold"> 
      <i:Interaction.Triggers> 
        <i:EventTrigger EventName="MouseLeftButtonDown"> 
          <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.MouseLeftButtonDown }"/> 
        </i:EventTrigger> 
      </i:Interaction.Triggers> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding Path=Name}" /> 
       <TextBlock Text="{Binding Path=Price}" /> 
      </StackPanel> 
     </Border> 
</DataTemplate> 

Ponieważ źródło Twojego ItemsControl jest zobowiązany do produktów to, DataTemplate za DataContext będzie obiekt produktu, aby uniknąć sytuacji, należy powiązać źródło danego polecenia do przodka okno, które jego DataContext jest związany ViewModel, który zawiera RelayCommand:

public class MainViewModel : ViewModelBase 
{ 


    public class Product 
    { 
     public string Name { get; set; } 
     public string Price { get; set; } 
    } 

    public List<Product> Products 
    { 
     get 
     { 
      return new List<Product>() 
        { 
         new Product(){Name = "Product1",Price = "Price1"}, 
         new Product(){Name = "Product2",Price = "Price2"} 
        }; 
     } 
    } 

    public RelayCommand MouseLeftButtonDown { get; set; } 

    public MainViewModel() 
    { 
      MouseLeftButtonDown = new RelayCommand(()=> MessageBox.Show("Message","Hi")); 
    } 
} 

PS: command:EventToCommand jest z MVVM-Light, jeśli nie korzystasz z MVVM-Light, którą możesz po prostu użyj tego zamiast:

<i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseLeftButtonDown"> 
       <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.MouseLeftButtonDown }" >    
       </i:InvokeCommandAction> 
     </i:EventTrigger> 
</i:Interaction.Triggers> 

To powinno idealnie działać, mam nadzieję, że dobrze wyjaśnione.

7

Można spróbować czegoś takiego:

<DataTemplate> 
     <Border BorderThickness="1" BorderBrush="Gold"> 
     <Border.InputBindings> 
      <MouseBinding MouseAction="LeftClick" Command="{Binding DataContext.SomeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"/> 
     </Border.InputBindings> 

     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="{Binding Path=Name}" /> 
      <TextBlock Text="{Binding Path=Price}" /> 
      </StackPanel> 
      </Border> 
</DataTemplate> 
+0

+1 dla wejścia wiążące, -1 dla 'komenda = "{Binding SomeCommand}"', DataContext z DataTemplate jest ustawiony do produktu (Model) nie wystarczy ViewModel – AymenDaoudi

+1

. Edytowane. – Den