Когда будет вызываться метод Convert ValueConverter в wpf - PullRequest
5 голосов
/ 12 мая 2010

У меня есть ObservableCollection , связанная с списком и логическое свойство, связанное с кнопкой . Затем я определил два преобразователя , один из которых работает с коллекцией, а другой - с логическим свойством. Всякий раз, когда я изменяю логическое свойство, вызывается метод преобразователя 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>   

код за фрагментом кода

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

Ответы [ 3 ]

15 голосов
/ 04 июня 2012

Для преодоления этой проблемы можно использовать мультисвязывающий преобразователь. Затем вы можете связать свойство 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>
12 голосов
/ 12 мая 2010

Я думаю, что конвертер в Binding всегда вызывается, если источник Binding был обновлен и уведомляет об этом обновлении (как DependencyProperty или используя INotifyPropertyChanged). Однако ObservableCollection не вызывает событие PropertyChanged, если элемент был добавлен или удален, но вызывает событие CollectionChanged. Это не вызывает никакого события вообще, если элемент в коллекции изменен. Даже если сам элемент поднимает PropertyChanged, это не приведет к обновлению Binding в коллекции, поскольку источником Binding является не элемент, а коллекция.

Боюсь, ваш подход не сработает таким образом. Вы можете связать напрямую с ObservableCollection.Count и добавить соответствующий математический преобразователь для выполнения инверсии и умножения, но свойство Count не выполняет уведомление об изменении, так что это не вариант. Я думаю, что вам придется предоставить другое свойство в вашей ViewModel или коде, который обрабатывает эти случаи ...

2 голосов
/ 12 мая 2010

Преобразователь вызывается, когда происходит привязка или изменяется свойство. Таким образом, ваш преобразователь вызывается для вашего логического значения всякий раз, когда значение логического значения изменяется. Ваша коллекция устанавливается один раз, и тогда происходит привязка и используется конвертер. Когда внутренние элементы коллекции изменяются (коллекция добавляется или удаляется из), свойство не изменяется (т. Е. Вы не привязываете новую коллекцию), поэтому преобразователь не запускается снова.

Используйте модель представления, оберните свою коллекцию и добавьте еще одно свойство, например count, которое реализует уведомление об изменении. Вы можете использовать этот класс-оболочку из здесь , который обернет вашу коллекцию, и будет легко добавить свойство туда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...