Получение 'ConvertBack (...)' для запуска выбора WPF ComboBox - PullRequest
1 голос
/ 11 мая 2011

У меня есть ComboBox со свойством Items, связанным с коллекцией объектов.У меня также есть свойство SelectedItem, связанное со всей коллекцией, с ValueConverter, предназначенным для проверки элементов в коллекции и возврата 1 элемента, который будет выбран.Эта часть работает.

Что не работает, так это когда пользователь делает изменение выбора в ComboBox, метод ConvertBack(...) для ValueConverter не вызывается.Мне нужно вызвать ConvertBack(...), потому что мне нужно принять выбор пользователя, пересмотреть коллекцию и соответственно отредактировать старый выбранный элемент и новый выбранный элемент.

Я знаю, что этот подход неудобен, но этотак оно и есть.Вот соответствующий код:

ComboBox:

<ComboBox ItemsSource="{Binding}" SelectedItem="{Binding Path=., Converter={StaticResource ResourceKey=DataInputAssetChoiceSelectedItemConverter}}" />

ValueConverter:

public class DataInputAssetChoiceSelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            foreach (CustomObject Choice in (Collection<CustomObject>)value)
            {
                if (Choice.IsSelected)
                {
                    return Choice;
                }
            }
            return ((Collection<CustomObject>)value).First();
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {   //breakpoint...execution never gets here!
        return null;
    }
}

Так почему же никогда не вызывается ConvertBack(...)?Это просто то, что я неправильно понимаю по поводу ComboBox?Я попробовал этот подход, используя SelectedItem, SelectedValue, SelectedIndex, и пытался связываться с UpdateSourceTrigger, различными режимами привязки, DataTriggers, и, кажется, никогда не получаю ConvertBack(...) для вызова.Является ли использование события SelectionChanged единственным вариантом?Если так, то почему?

Ответы [ 2 ]

4 голосов
/ 11 мая 2011

Вы не привязываетесь к свойству, поэтому Binding не может ничего установить.Вы привязываетесь непосредственно к объекту DataContext, и Binding не будет обновлять это.

Если у вас было {Binding Path=SomeProperty, Converter=...}, то вызывался бы ConvertBack.Хотя в нынешнем виде он не будет называться.

2 голосов
/ 11 мая 2011

Вы правы, это неудобно, но только потому, что вы пытаетесь добавить некоторое управление в коллекцию в преобразователе значений, а не в самой коллекции.Я думаю, что было бы полезно, если бы ваша коллекция больше знала, что ее элементы имеют свойство IsSelected:

public CustomCollection : Collection<CustomObject> {
    CustomObject _current;
    public CustomObject CurrentSelection {
        get { return _current; }
        set {
            if (_current == value)
                return;

            if (_current != null)
                _current.IsSelected = false;

            if (value != null)
                value.IsSelected = true;

            _current = value;
        }
    }
}

Просто добавьте немного больше, чтобы убедиться, что _current является по крайней мере первым элементом вколлекция.

<ComboBox ItemsSource="{Binding}" SelectedItem="{Binding CurrentSelection}">

Теперь вам больше не нужен конвертер.Однако некоторые соображения отсутствуют.Возможно, вы захотите использовать ObservableCollection<T> вместо этого и вызвать событие PropertyChanged при изменении CurrentSelection, чтобы, если с этим свойством было связано что-либо еще или оно изменилось в коде, все привязки будут обновлены соответствующим образом.

Редактировать : обтекание модели

Один простой способ обернуть коллекцию вместо создания пользовательской коллекции, как указано выше:

public class CollectionWrapper : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged = (o,e)=>{};
    // never have to check for null

    public CollectionWrapper(Collection<CustomObject> collection) {
        Items = collection;
    }

    // unlikely to change, so let's prevent it for now
    public Collection<CustomObject> Items {
        get;
        private set;
    }

    CustomObject _current;
    public CustomObject CurrentSelection {
        get { return _current; }
        set {
            if (_current == value)
                return;

            if (_current != null)
                _current.IsSelected = false;

            if (value != null)
                value.IsSelected = true;

            _current = value;
            PropertyChanged(this, new PropertyChangedEventArgs("CurrentSelection"));
        }
    }
}

Тогда этот объект становится вашим контекстом данныхи привязки ComboBox изменяются на:

<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding CurrentSelection}">
...