Wann wird der Valueconverter der Methode Konvertieren in wpf aufgerufen werden
-
26-09-2019 - |
Frage
Ich habe eine ObservableCollection gebunden an ein Listenfeld und boolean Eigenschaft gebunden an einen . Ich habe dann definiert zwei Konverter , eine, die auf der Sammlung arbeitet und der andere arbeitet auf der boolean-Eigenschaft. Jedes Mal, wenn ich die Boolesche Eigenschaft ändern, die Umsetzers Convert Methode aufgerufen wird, wo als das gleiche ist nicht genannt, wenn ich die beobachtbaren Sammlung ändern. Was bin ich fehlt ??
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-behind-Schnipsel
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();
}
}
Lösung
Ich denke, der Wandler in einem Binding
immer, wenn die Binding
Quelle genannt wird, wird aktualisiert und meldet über dieses Update (als DependencyProperty
oder mit INotifyPropertyChanged
). Allerdings ist ein ObservableCollection
nicht PropertyChanged
Ereignis auslösen, wenn ein Element hinzugefügt oder entfernt wurde, aber es stellt sich die CollectionChanged
Ereignis. Es macht keinen Fall überhaupt erheben, wenn ein Element in der Auflistung geändert wird. Selbst wenn der Gegenstand selbst PropertyChanged
wirft, wird dies nicht den Binding
auf der Sammlung aktualisieren, da die Binding
Quelle nicht der Gegenstand ist, aber die Sammlung.
Ich fürchte, Ihr Ansatz wird auf diese Weise nicht funktionieren. Sie könnten direkt an ObservableCollection.Count
binden und einen geeigneten Mathe-Wandler, um es hinzuzufügen die Inversion und Multiplikation durchzuführen, aber die Count
Eigenschaft nicht Änderungsmitteilung, so dass dies keine Option auszuführen. Ich denke, dass Sie eine andere Eigenschaft in Ihrem Ansichtsmodell oder Code-behind zu bieten haben, die diese Fälle behandelt ...
Andere Tipps
Ein mehrbindigen Konverter kann verwendet werden, um dieses Problem zu überwinden. Anschließend können Sie binden an die Collection.Count Eigenschaft und die Sammlung zur gleichen Zeit. Die Zahl löst die neu bewertet bekommen Bindung und dann verwenden Sie die zweite Bindung, die Werte tatsächlich zu transformieren, wie erforderlich
<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>
A-Wandler wird aufgerufen, wenn die Bindung geschieht oder die Eigenschaft ändert. Also Ihr Konverter für Ihre boolean, wenn der Wert der Booleschen Änderungen aufgerufen wird. Ihre Sammlung wird einmal und das ist, wenn die Bindung auftritt, und der Wandler verwendet wird. Wenn die Interna der Sammlung Änderung (die Sammlung hinzugefügt oder entfernt von) die Eigenschaft nicht ändert (das heißt Sie eine neue Kollektion nicht bindend), damit Ihr Konverter nicht wieder Feuer.
Verwenden Sie ein Ansichtsmodell und Ihre Sammlung wickeln und eine andere Eigenschaft wie Zahl hinzufügen, dass Geräte Benachrichtigung ändern. Sie können diese Wrapper-Klasse verwenden, um von hier die Ihre Sammlung wickeln und es wird leicht sein, eine Eigenschaft dort hinzufügen .