2016-02-29 2 views
0

J'ai créé ControlTemplates:DataTrigger binded à la propriété dans ViewModel ne se déclenche pas dans le bouton de DataGrid

<Window.Resources> 
    <ControlTemplate x:Key="imgNo" TargetType="{x:Type Control}"> 
     <Image Source="pack://application:,,,/Images/up.png"/> 
    </ControlTemplate> 

    <ControlTemplate x:Key="imgUp" TargetType="{x:Type Control}"> 
     <!--<TextBlock Text="Up"/>--> 
     <Image Source="pack://application:,,,/Images/up.png"/> 
    </ControlTemplate> 

    <ControlTemplate x:Key="imgDown" TargetType="{x:Type Control}"> 
     <Image Source="pack://application:,,,/Images/downArrow.png"/> 
    </ControlTemplate> 

    <DataTemplate x:Key="ButtonOneDataTemplate"> 
     <Control x:Name="theControl" Template="{DynamicResource imgNo}" /> 
     <DataTemplate.Triggers> 
      <DataTrigger Binding="{Binding IsImageChanged}" Value="true"> 
       <Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgUp}" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding IsImageChanged}" Value="false"> 
       <Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgDown}" /> 
      </DataTrigger> 
     </DataTemplate.Triggers> 
    </DataTemplate> 
</WindowResources> 

et Button dans DataGrid qui utilise ci-dessus ControlTemplates:

<DataGrid ItemsSource="{Binding Persons}" Grid.Row="1" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
    <DataGridTextColumn Binding="{Binding IdPerson}"> 
     <DataGridTextColumn.HeaderTemplate>       
      <DataTemplate> 
      <Border Background="Violet"> 
      <StackPanel> 
       <Button ContentTemplate="{StaticResource ButtonOneDataTemplate}" 
       Command="{Binding DataContext.HelloCommand, RelativeSource= 
        {RelativeSource AncestorType=Window}}" 
        CommandParameter="{Binding DataContext.Hello, 
       RelativeSource={RelativeSource AncestorType=DataGrid}}"/> 
      </StackPanel> 
      </Border> 
     </DataTemplate> 
     </DataGridTextColumn.HeaderTemplate>     
    </DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid>      

Mon ViewModel:

public class MainWindowViewModel:ViewModelBase 
{ 
    public RelayCommand HelloCommand { get; set; } 
    public MainWindowViewModel() 
    { 
     LoadPersons(); 
     HelloCommand = new RelayCommand(SayHello); 
    } 

    int helloCounter = 0; 
    private void SayHello(object obj) 
    { 
     if (helloCounter % 2 == 0) 
      IsImageChanged = true; 
     else 
      IsImageChanged = false;   
     helloCounter++; 
    } 


    private bool isImageChanged=true; 
    public bool IsImageChanged 
    { 
     get { return isImageChanged; } 
     set { isImageChanged = value; 
      OnPropertyChanged("IsImageChanged"); 
      } 
    } 
} 

Ce que je veux, c'est quand je clique sur le bouton <Button ContentTemplate="{StaticResource ButtonOneDataTemplate}"/>, puis Template devrait être remplacé par {DynamicResource imgDown} ou {DynamicResource imgUp}. DataTrigger dépend de la valeur IsImageChanged.

Cependant, si je clique sur le Button, puis DataTrigger ne se déclenche pas (Controltemplates tels que imgUp, imgDown ne sont pas modifiés). Comment puis-je y parvenir à partir de mon ViewModel?

+0

Pls fournit le code du mode de visualisation complet. . – Gopichandar

+0

Encore vous n'êtes pas clair avec l'objectif. Qu'est-ce que vous essayez d'atteindre avec cela? – Gopichandar

+0

@Gopichandar s'il vous plaît voir ma question mise à jour – StepUp

Répondre

1

Le problème est que la colonne DataGrid ne fait pas partie d'une arborescence visuelle et, pour cette raison, elle n'hérite pas de DataContext. Pour être en mesure d'utiliser DataTriggers dans votre ButtonOneDataTemplate vous avez besoin de ce bouton, vous appliquant ce modèle à, a DataContext correct. Il y a un truc, comment fournir DataContext à des éléments qui ne sont pas VisualTree, décrit here

application de cette solution à votre code, nous allons avoir les éléments suivants:

Proxy

public class BindingProxy : Freezable 
{ 
    #region Overrides of Freezable 

    protected override Freezable CreateInstanceCore() 
    { 
     return new BindingProxy(); 
    } 

    #endregion 

    public object Data 
    { 
     get { return (object)GetValue(DataProperty); } 
     set { SetValue(DataProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty DataProperty = 
     DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 
} 

fenêtre. ressources

<local:BindingProxy x:Key="proxy" Data="{Binding}" /> 

    <DataTemplate x:Key="ButtonOneDataTemplate"> 
     <Control x:Name="theControl" Template="{DynamicResource imgNo}" Foreground="Orange"/> 
     <DataTemplate.Triggers> 
      <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.IsImageChanged}" Value="True"> 
       <Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgUp}" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.IsImageChanged}" Value="False"> 
       <Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgDown}" /> 
      </DataTrigger> 
     </DataTemplate.Triggers> 
    </DataTemplate> 

HeaderTemplate

<DataGridTextColumn.HeaderTemplate> 
    <DataTemplate> 
     <Border Background="Violet"> 
      <StackPanel> 
       <Button ContentTemplate="{StaticResource ButtonOneDataTemplate}" 
         DataContext="{Binding Path=Data, Source={StaticResource proxy}}" 
         Command="{Binding DataContext.ButtonClick, RelativeSource={RelativeSource AncestorType=Window}}" 
         CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid}}"/> 
      </StackPanel> 
     </Border> 
    </DataTemplate> 
</DataGridTextColumn.HeaderTemplate> 
+0

Million merci, Man! Ca marche vraiment! :) Merci beaucoup! – StepUp

+1

Vous êtes les bienvenus :) –