1

我有一个绑定到对象集合的属性ComboBoxItems我还有SelectedItem绑定到整个集合的属性,ValueConverter旨在检查集合中的元素并返回要选择的 1 个项目。这部分有效。

不起作用的是当用户在 ComboBox 上进行选择更改时,不会调用的ConvertBack(...)方法。ValueConverter我需要ConvertBack(...)调用,因为我需要接受用户的选择,重新检查集合,并适当地编辑旧的选定项目和新选定的项目。

我知道这种方法很尴尬,但就是这样。以下是相关代码:

组合框:

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

值转换器:

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事件是唯一的选择吗?如果是这样,为什么?

4

2 回答 2

4

您没有绑定到属性,因此 Binding 无法设置任何内容。您直接绑定到 DataContext 对象,并且 Binding 不会更新它。

如果你有{Binding Path=SomeProperty, Converter=...},那么将调用 ConvertBack。尽管如此,它不会被调用。

于 2011-05-11T17:54:15.350 回答
2

你是对的,这很尴尬,但这只是因为你试图在价值转换器而不是在集合本身上向集合添加一些管理。我认为,如果您的收藏更清楚其项目具有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}">
于 2011-05-11T18:11:52.020 回答