2009-08-10 6 views
20

Ho lottato con questo codice da un po 'di tempo e non riesco a trovare nessuna risposta completa alla mia domanda. Ho creato un piccolo esempio per illustrare il problema:L'attributo di binding delle condizioni non funziona?

<ListView > 
    <ListView.ItemsPanel> 
     <ItemsPanelTemplate> 
     <StackPanel Margin="0,0,20,0" IsItemsHost="True" /> 
    </ItemsPanelTemplate> 
    </ListView.ItemsPanel> 
    <ListView.Items> 
     <TextBlock>Test1</TextBlock> 
     <TextBlock>Test2</TextBlock> 
     <TextBlock>Test3</TextBlock> 
     <TextBlock>Test4</TextBlock> 
     <TextBlock>Test5</TextBlock> 
    </ListView.Items> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="{x:Type ListViewItem}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ListViewItem}"> 
        <Grid> 
         <ContentPresenter/> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True" /> 
           <Condition Property="IsSelected" Value="True"/> 
          </MultiTrigger.Conditions> 
          <Setter Property="Visibility" Value="Collapsed"/> 
         </MultiTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     </Style> 
    </ListView.ItemContainerStyle> 
</ListView> 

Secondo le impostazioni MultiTrigger, l'elemento selezionato dovrebbe riapparire quando il mouse non è più sopra l'elemento selezionato. Questo codice, tuttavia, produce una InvalidOperationException con il messaggio "Deve avere valore non nullo per 'Proprietà'." Se si rimuove la condizione che utilizza l'attributo "Binding", l'eccezione non viene generata. Nella documentazione MSDN, afferma che è necessario avere l'attributo Property o Binding. Il codice sopra funziona come l'attributo Binding non è impostato. In effetti, in tutti i miei casi di test, non importa quale sia l'attributo Binding impostato; l'eccezione è ancora generata. qualche idea?

risposta

52

Questa è una di quelle volte in cui devi succhiarla e ammettere di aver commesso un errore di osso. Tuttavia, per salvare un'altra anima sfortunata dallo stesso destino, rivelerò la mia epifania.

In primo luogo, se avessi letto tutte la documentazione che avrei letto la parte che ha detto che se si sta utilizzando l'attributo "vincolante" della condizione, deve essere incluso in un elemento MultiDataTrigger (al posto del MutiTrigger elemento nel mio esempio pubblicato).

secondo luogo, al momento della tali modifiche, l'elemento MultiTrigger è sostituire con il codice seguente:

<MultiDataTrigger> 
    <MultiDataTrigger.Conditions> 
     <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True" /> 
     <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"/> 
    </MultiDataTrigger.Conditions> 
    <Setter Property="Visibility" Value="Collapsed"/> 
</MultiDataTrigger> 

ora all'esempio funziona ma perché l'elemento selezionato è compresso, la condizione di trigger passa avanti e indietro causando selezionato elemento da sfarfallio dentro e fuori dalla vista. Ha senso ma, ammettiamolo, non è quello che intendevo.

In ogni caso, spero che questo aiuti qualcuno a commettere lo stesso errore di osso!

+2

+1 per l'ammissione di boneheadedness e fornendo una soluzione. Qualcun altro si imbatterà in questo. Manca la parola "Dati" è abbastanza facile da trascurare. –

+3

+1 Per avermi condotto alla soluzione molto più rapidamente rispetto alla ricerca e alla lettura della documentazione. L'errore avrebbe dovuto spiegare questo invece di fare affidamento sulla documentazione. – jpierson

+1

+1 Ho appena fatto la stessa mossa con la testa di osso. Il tuo post probabilmente mi ha salvato un'ora. –

3

Su una nota molto simile, estrazione di IsMouseOver da un bordo come contenuto del modello dati principale e estrazione di IsSelected dall'Antenitor. È interessante notare che entrambe le condizioni devono avere un percorso relativo, suppongo che il percorso predefinito sia il datacontext locale. Grazie per la soluzione di cui sopra.

rotto Codice

<MultiDataTrigger> 
    <MultiDataTrigger.Conditions> 
     <Condition Binding="{Binding Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" 
        Value="True" /> 
     <Condition SourceName="Border" 
        Property="IsMouseOver" 
        Value="True" /> 
    </MultiDataTrigger.Conditions> 
    <Setter TargetName="Border" 
      Property="Background" 
      Value="{StaticResource OnBrushSelected}" /> 
</MultiDataTrigger> 

codice di lavoro

<MultiDataTrigger> 
    <MultiDataTrigger.Conditions> 
     <Condition Binding="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}, Path=IsMouseOver}" 
        Value="True" /> 
     <Condition Binding="{Binding Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" 
        Value="True" /> 
    </MultiDataTrigger.Conditions> 
    <Setter TargetName="Border" 
      Property="Background" 
      Value="{StaticResource OnBrushSelected}" /> 
</MultiDataTrigger> 
+0

Questo mi ha aiutato, grazie. +1 – Dessus

+0

Voglio chiamare questo un altro mito WPF che non segue alcuna convenzione !? – mkb