我有 ObservableCollection 绑定到列表框,布尔属性绑定到按钮。然后我定义了两个转换器,一个对集合进行操作,另一个对boolean属性进行操作。每当我修改boolean属性时,都会调用转换器的 Convert 方法,如果我修改了observable集合,则不会调用它。我错过了什么?
摘录供您参考,
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>
片段后面的代码
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();
}
}
答案 0 :(得分:15)
可以使用多重绑定转换器来克服此问题。然后,您可以同时绑定到Collection.Count属性和集合。计数将触发绑定以重新评估,然后使用第二个绑定实际转换所需的值
<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>
答案 1 :(得分:12)
我认为Binding
中的转换器始终在Binding
源已更新时被调用,并通知该更新(作为DependencyProperty
或使用INotifyPropertyChanged
ObservableCollection
)。但是,PropertyChanged
如果已添加或删除某个项目,则不会引发PropertyChanged
事件,但会引发CollectionChanged
事件。如果集合中的项目发生更改,它根本不会引发任何事件。即使项目本身引发Binding
,也不会更新集合上的Binding
,因为ObservableCollection.Count
来源不是项目,而是集合。
我担心你的做法不会这样。您可以直接绑定到Count
并为其添加适当的数学转换器以执行反转和乘法,但{{1}}属性不会执行更改通知,因此这没有选项。我认为您必须在ViewModel或代码隐藏中提供另一个属性来处理这些情况......
答案 2 :(得分:2)
当绑定发生或属性更改时,将调用转换器。因此,只要布尔值发生变化,就会调用转换器的布尔值。您的集合设置一次,即绑定发生时使用转换器。当集合的内部更改(添加或删除集合)时,属性不会更改(即您没有绑定新集合),因此转换器不会再次触发。
使用视图模型并包装您的集合并添加另一个属性,例如实现更改通知的计数。您可以使用here中的这个包装类来包装您的集合,并且可以很容易地在那里添加属性。