Конвертеры WPF и ObservableCollections - PullRequest
3 голосов
/ 27 июня 2011

Я привязываю ObservableCollection к элементу управления, у которого есть конвертер, чтобы изменить его видимость в зависимости от того, имеет ли коллекция какие-либо значения:

Упрощенный пример:

XAML:

<Window.Resources>
    <local:MyConverter x:Key="converter"/>
</Window.Resources>

<Grid x:Name="grid">
    <Rectangle Height="100" Width="200" Fill="CornflowerBlue"
                Visibility="{Binding Converter={StaticResource converter}}"/>
    <Button Content="click" 
            HorizontalAlignment="Left" VerticalAlignment="Top" 
            Click="Button_Click"/>
</Grid>

C #:

ObservableCollection<string> strings;

public MainWindow()
{
    InitializeComponent();

    strings = new ObservableCollection<string>();
    grid.DataContext = strings;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    strings.Add("new value");
}

Когда коллекция связана, прямоугольник виден, когда есть значения, а не когда коллекция пуста. Однако, если коллекция пуста, и я добавляю значение во время выполнения, Rectangle не появляется (метод Convert конвертера даже не запускается). Я что-то упускаю или просто пытаюсь спросить слишком много об IValueConverter?

Ответы [ 3 ]

2 голосов
/ 27 июня 2011

ОК, вот как я обошёл проблему, используя MultiValueConverter

. Теперь конвертер выглядит так:

public object Convert(
    object[] values, 
    Type targetType, 
    object parameter, 
    System.Globalization.CultureInfo culture)
{
    ObservableCollection<string> strings = 
        values[0] as ObservableCollection<string>;

    if (strings == null || !strings.Any())
        return Visibility.Collapsed;
    else
        return Visibility.Visible;
}

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

И XAML теперь выглядит так:

<Rectangle Height="100" Width="200" Fill="CornflowerBlue">
    <Rectangle.Visibility>
        <MultiBinding Converter="{StaticResource converter}">
            <Binding Path="."/>
            <Binding Path="Count"/>
        </MultiBinding>
    </Rectangle.Visibility>
</Rectangle>

C # остается прежним:)

1 голос
/ 27 июня 2011

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

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

С наилучшими пожеланиями,

0 голосов
/ 27 июня 2011

Вы должны установить DataContext после создания коллекции; вполне вероятно, что вы инициализируете коллекцию «strings» как «null», вы устанавливаете DataContext в конструкторе на это значение (например, null), а затем фактически создаете коллекцию - таким образом, DataContext остается нулевым.

Вы должны установить DataContext снова после создания коллекции.

...