2009-08-10 6 views
20

Od pewnego czasu walczę z tym kodem i nie mogę znaleźć żadnych pełnych odpowiedzi na moje pytanie. Utworzyłem małą próbkę do zilustrowania problemu:Atrybut wiązania warunku nie działa?

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

Zgodnie z ustawieniami MultiTrigger, wybrana pozycja powinna się ponownie, gdy mysz nie jest już na wybranej pozycji. Ten kod generuje wyjątek InvalidOperationException z komunikatem "Musi mieć wartość inną niż null dla" Właściwość "." Jeśli usuniesz warunek, który używa atrybutu "Wiązanie", wyjątek nie zostanie zgłoszony. W dokumentacji MSDN stwierdza, że ​​musisz mieć zestaw atrybutów Property lub Binding. Powyższy kod działa tak, jak atrybut Binding nie jest ustawiony. W rzeczywistości we wszystkich moich przypadkach testowych nie ma znaczenia, do czego jest ustawiony atrybut Wiązania; wyjątek jest nadal rzucany. jakieś pomysły?

Odpowiedz

52

To jeden z tych momentów, kiedy trzeba go ssać i przyznać, że popełniłeś błąd. Jednak, aby ocalić inną nieszczęśliwą duszę przed tym samym losem, ujawnię moje objawienie.

Po pierwsze, jeśli czytałem wszystko dokumentacji bym przeczytał część, która mówi, że jeśli używasz „wiązanie” atrybut Warunkiem jest, że musi być zawarte w elemencie MultiDataTrigger (zamiast MutiTrigger element w moim wysłanym przykładzie).

Po drugie, po co te zmiany, element MultiTrigger ma zastąpić za pomocą następującego kodu:

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

Teraz przykład działa, ale dlatego, że wybrana pozycja jest zwinięty, warunek wyzwalania przełącza się tam iz powrotem, powodując wybrana element do pojawiania się i oddalania. Ma sens, ale co prawda nie to, co zamierzałem.

W każdym razie, miej nadzieję, że pomaga to komuś w popełnieniu tego samego pomyłki!

+2

+1 przyjmowania boneheadedness i dostarczenie rozwiązania. Ktoś inny wybiegnie przeciwko temu. Brakujące słowo "Dane" łatwo przeoczyć. –

+3

+1 Za doprowadzenie mnie do rozwiązania o wiele szybciej niż polowanie i czytanie dokumentacji. Błąd powinien wyjaśnić to, zamiast polegać na dokumentacji. – jpierson

+1

+1 Po prostu zrobiłem ten sam ruch w kościach. Twój post prawdopodobnie zaoszczędził mi godzinę. –

3

W bardzo podobnej notatce, wyciągając IsMouseOver z obramowania jako główną treść szablonu danych i wyciągając IsSelected z Przodka. Ciekawe, że oba warunki muszą mieć względną ścieżkę, zakładam, że domyślną ścieżką będzie lokalny datacontext. Dzięki za powyższe rozwiązanie.

Złamane Kod

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

Kodeks Pracy

<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

Pomogło mi to, dzięki. +1 – Dessus

+0

Chcę nazwać ten inny mit WPF, który nie jest zgodny z żadną konwencją! – mkb