難看的解決方案
我創建了自己的MyComboBox,它從System.Windows.Controls.ComboBox.中繼承了MyComboBox i重寫了ItemsSourceProperty的元數據,因此只要更改了public partial class MyComboBox : ComboBox
{
static MyComboBox()
{
ItemsSourceProperty.OverrideMetadata(typeof(MyComboBox),
new FrameworkPropertyMetadata((IEnumerable)null, new PropertyChangedCallback(OnItemsSourceChanged)));
}
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ItemsControl ic = (ItemsControl)d;
IEnumerable oldValue = (IEnumerable)e.OldValue;
IEnumerable newValue = (IEnumerable)e.NewValue;
// We get into infinite recursion land without the following condition:
if (newValue.GetType() == typeof(Dictionary))
{
var cvs = new CollectionViewSource() { Source = ((Dictionary)newValue) };
ic.ItemsSource = cvs.View;
}
}
...
請注意if (newValue.GetType() == typeof(Dictionary))條件是必需的,否則將進入無限遞歸循環( MyComboBox集合ItemsControl.ItemsSource從而更改ItemsSourceProperty,然後觸發ic.ONIMSOURCE已更改( oldValue,newValue )返回到MyComboBox.OnTimesSourceChanged等等。
另一個警告:簡單地ic.ItemsSource = new ListCollectionView(((Dictionary)newValue).ToList());除非對基礎ObservableCollection的更改不會更新綁定combobox,否則有效,有必要創建新的CollectionViewSource,設置源,並綁定到視圖,如上所示,這也是在CollectionView的官方文檔:
不應在代碼中創建此類的對象,若要為僅實現IEnumerable的集合創建集合視圖,請創建一個CollectionViewSource對象,將集合添加到Source屬性,並從集合視圖獲取屬性。
上面的程序可運行,但是很醜陋。