【问题标题】:When will the ValueConverter's Convert method be called in wpfwpf什么时候调用ValueConverter的Convert方法
【发布时间】:2011-02-18 11:00:39
【问题描述】:

我有一个绑定到 列表框ObservableCollection 和一个绑定到 按钮boolean 属性。然后我定义了两个转换器,一个对集合进行操作,另一个对布尔属性进行操作。每当我修改布尔属性时,都会调用转换器的 Convert 方法,而如果我修改可观察集合,则不会调用相同的方法。我错过了什么??

片段供您参考,

xaml 片段,

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

sn-p 后面的代码

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();
    }
}   

【问题讨论】:

    标签: wpf observablecollection inotifypropertychanged converters


    【解决方案1】:

    可以使用多重绑定转换器来解决这个问题。然后,您可以同时绑定到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>
    

    【讨论】:

    • 感谢您提出这个想法!虽然上述答案对我来说根本不起作用,但这个答案确实有效。我需要稍微修改一下我的转换器以实现 IMultiValueConverter 而不是 IValueConverter,并且我需要明确我的集合将在哪个索引处,但是一切都很好。
    【解决方案2】:

    我认为如果 Binding 源已更新并通知该更新(作为 DependencyProperty 或使用 INotifyPropertyChanged),则始终调用 Binding 中的转换器。但是,如果已添加或删除项目,ObservableCollection 不会引发 PropertyChanged 事件,但会引发 CollectionChanged 事件。如果集合中的项目发生更改,它根本不会引发任何事件。即使项目本身引发PropertyChanged,这也不会更新集合上的Binding,因为Binding 源不是项目,而是集合。

    我担心你的方法不会这样。您可以直接绑定到ObservableCollection.Count 并向其添加适当的数学转换器以执行求逆和乘法,但Count 属性不执行更改通知,因此没有选项。我认为您将不得不在处理这些情况的 ViewModel 或代码隐藏中提供另一个属性...

    【讨论】:

    • 每当将一个项目添加到集合中时,ObservableCollection 成员都会引发 CollectionModified 事件。只有在修改属性时才会触发转换器。作为一种解决方法,可以订阅集合修改事件,然后使用 ObservableCollection 的属性名称引发 PropertyChanged 事件。
    • 刚刚看到你的回复,我也有同样的推断。
    • 您的解决方法可能有效,但您应该知道此解决方法将更新完整的绑定,即重新读取集合并再次创建集合中的所有项目。至少,这是我所期望的。我宁愿建议绑定到自定义 Count 属性,但这取决于您的场景是否值得开销。
    【解决方案3】:

    当绑定发生或属性改变时调用转换器。因此,只要布尔值发生变化,就会为您的布尔值调用转换器。您的集合设置一次,即发生绑定并使用转换器。当集合的内部发生变化(添加或删除集合)时,属性不会改变(即您没有绑定新集合),因此您的转换器不会再次触发。

    使用视图模型并包装您的集合并添加另一个属性,例如实现更改通知的计数。您可以使用here 中的这个包装类,它将包装您的集合,并且很容易在其中添加一个属性。

    【讨论】:

      猜你喜欢
      • 2011-07-21
      • 1970-01-01
      • 2015-07-13
      • 2012-11-30
      • 1970-01-01
      • 2012-05-16
      • 2018-01-01
      相关资源
      最近更新 更多