我有一个ComboBox
,其Items
属性绑定到一组对象。我还有SelectedItem
属性绑定到整个集合,ValueConverter
用于检查集合中的元素并返回要选择的1项。这部分有效。
什么不起作用是当用户在ComboBox上进行选择更改时,ConvertBack(...)
的{{1}}方法未被调用。我需要调用ValueConverter
因为我需要进行用户选择,重新检查集合,并适当地编辑旧的所选项目和新选择的项目。
我知道这种做法很尴尬,但事实就是如此。这是相关的代码:
组合框:
ConvertBack(...)
ValueConverter:
<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
,各种绑定模式,DataTriggers,似乎永远不会得到{{} 1}}被召唤。使用UpdateSourceTrigger
事件是唯一的选择吗?如果是这样,为什么?
答案 0 :(得分:3)
您没有绑定到属性,因此Binding无法设置任何内容。您直接绑定到DataContext对象,Binding不会更新它。
如果您有{Binding Path=SomeProperty, Converter=...}
,则会调用ConvertBack。尽管如此,它不会被调用。
答案 1 :(得分: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}">