5

in wpf nennen Ich habe eine ObservableCollection zu einer Box Liste gebunden und boolean Eigenschaft auf einen gebunden Taste. Ich definierte dann zwei Konverter, einer, der auf der Sammlung arbeitet und der andere auf der booleschen Eigenschaft arbeitet. Immer wenn ich die boolesche Eigenschaft ändere, wird die Convert Methode des Converters aufgerufen, wobei das gleiche nicht aufgerufen wird, wenn ich die beobachtbare Sammlung modifiziere. Was vermisse ich??Wann wird die Methode Konvertieren des Valueconverter

Snippets für Ihre Referenz,

XAML snipet,

<Window.Resources> 
    <local:WrapPanelWidthConverter x:Key="WrapPanelWidthConverter" /> 
    <local:StateToColorConverter x:Key="StateToColorConverter" /> 
</Window.Resources> 
<StackPanel> 
    <ListBox x:Name="NamesListBox" ItemsSource="{Binding Path=Names}"> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel x:Name="ItemWrapPanel" Width="500" Background="Gray"> 
        <WrapPanel.RenderTransform> 
         <TranslateTransform x:Name="WrapPanelTranslatation" X="0" /> 
        </WrapPanel.RenderTransform> 
        <WrapPanel.Triggers> 
         <EventTrigger RoutedEvent="WrapPanel.Loaded"> 
          <BeginStoryboard> 
           <Storyboard> 
            <DoubleAnimation Storyboard.TargetName="WrapPanelTranslatation" Storyboard.TargetProperty="X" To="{Binding Path=Names,Converter={StaticResource WrapPanelWidthConverter}}" From="525" Duration="0:0:2" RepeatBehavior="100" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </EventTrigger> 
        </WrapPanel.Triggers> 
       </WrapPanel> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Label Content="{Binding}" Width="50" Background="LightGray" /> 
       </Grid> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Content="{Binding Path=State}" Background="{Binding Path=State, Converter={StaticResource StateToColorConverter}}" Width="100" Height="100" Click="Button_Click" /> 
</StackPanel> 

Code hinter Snippet

public class WrapPanelWidthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ObservableCollection<string> aNames = value as ObservableCollection<string>; 
     return -(aNames.Count * 50); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 


public class StateToColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     bool aState = (bool)value; 
     if (aState) 
      return Brushes.Green; 
     else 
      return Brushes.Red; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Antwort

11

Ich denke, der Wandler in einem Binding immer, wenn die Binding Quelle genannt wird, wurde aktualisiert und benachrichtigt über dieses Update (als DependencyProperty oder mit INotifyPropertyChanged). Ein ObservableCollection löst jedoch das Ereignis PropertyChanged nicht aus, wenn ein Element hinzugefügt oder entfernt wurde, aber es löst das Ereignis CollectionChanged aus. Es wird kein Ereignis ausgelöst, wenn ein Element in der Sammlung geändert wird. Auch wenn das Element selbst PropertyChanged erhöht, wird dies die Binding auf der Sammlung nicht aktualisieren, da die Binding Quelle nicht das Element, sondern die Sammlung ist.

Ich fürchte, Ihr Ansatz wird so nicht funktionieren. Sie können direkt an 10 binden und einen entsprechenden mathematischen Konverter hinzufügen, um die Inversion und Multiplikation durchzuführen, aber die Count Eigenschaft führt keine Änderungsbenachrichtigung aus, daher diese Option. Ich denke, Sie müssen eine andere Eigenschaft in Ihrem ViewModel oder Code-Behind, die diese Fälle behandelt ...

+0

Jedes Mal, wenn ein Element der Sammlung hinzugefügt wird, ist die ObservableCollection Mitglied CollectionModified Anhebung Veranstaltung. Wo die Konverter nur ausgelöst werden, wenn die Eigenschaft geändert wird. Um dieses Problem zu umgehen, können Sie das geänderte Sammlungsereignis abonnieren und dann das PropertyChanged-Ereignis mit dem Objeknamen der ObservableCollection auslösen. – sudarsanyes

+0

Gerade ist jetzt auf Ihre Antwort gestoßen und ich habe auch das gleiche abgeleitet. – sudarsanyes

+0

Ihre Problemumgehung kann funktionieren, aber Sie sollten sich bewusst sein, dass diese Problemumgehung wird die vollständige Bindung aktualisieren, das heißt die Sammlung lesen neu ist und alle Elemente in Ihrer Sammlung werden wieder angelegt. Zumindest würde ich das erwarten. Ich würde eher empfehlen, an eine benutzerdefinierte "Count" -Eigenschaft zu binden, aber es hängt von Ihrem Szenario ab, ob es den Overhead wert ist. – gehho

2

Ein Konverter wird aufgerufen, wenn die Bindung passiert oder die Eigenschaft ändert. Daher wird Ihr Konverter immer dann für Ihren Booleschen Wert aufgerufen, wenn sich der Wert des Boolean ändert. Ihre Sammlung wird einmal festgelegt und das ist der Zeitpunkt, zu dem die Bindung erfolgt und der Konverter verwendet wird. Wenn sich die Interna der Sammlung ändern (die Sammlung wird hinzugefügt oder entfernt), ändert sich die Eigenschaft nicht (d. H. Sie binden keine neue Sammlung), sodass der Konverter nicht erneut ausgelöst wird.

Verwenden Sie ein Ansichtsmodell, umbrechen Sie die Auflistung, und fügen Sie eine weitere Eigenschaft hinzu, z. B. count, die die Änderungsbenachrichtigung implementiert. Sie können diese Wrapperklasse von here verwenden, die Ihre Sammlung umschließt, und es wird einfach sein, dort eine Eigenschaft hinzuzufügen.

11

Ein Multibinderkonverter kann verwendet werden, um dieses Problem zu lösen. Sie können dann gleichzeitig an die Collection.Count-Eigenschaft und die Auflistung binden. Die Zählung wird die Bindung auslösen neu bewertet zu bekommen und dann verwenden Sie die zweite Bindung an die Werte tatsächlich transformieren nach Bedarf

      <TextBlock IsHitTestVisible="false" 
           Margin="5,0" 
           TextTrimming="CharacterEllipsis" 
           VerticalAlignment="Center" 
           DockPanel.Dock="Left" > 
           <TextBlock.Text> 
            <MultiBinding Converter="{Resources:ListToStringConverter}"> 
             <Binding Path="List.Count" /> 
             <Binding Path="List" /> 
            </MultiBinding> 
           </TextBlock.Text> 
          </TextBlock> 
+0

Vielen Dank für diese Idee! Während die obigen Antworten für mich überhaupt nicht funktionierten, tut dieser eine. Ich brauche meinen Konverter ein wenig zu modifizieren IMultiValueConverter statt IValueConverter zu implementieren, und ich muß deutlich machen, an dem Index meiner Sammlung sein wird, aber dann ist alles in Ordnung. – ygoe

+0

Brilliant! Diese Idee hat mir nur eine Menge Zeit erspart. – gbc

+0

Ausgezeichnet, danke! – Aybe