對,因爲DataGridView試圖在每個DataTemplate實例化中緩存和重用ComboBox,所以很難得到正確的結果。我有一個類似的情況,我想要一個「過濾」組合框,根據用戶迄今爲止輸入的內容來過濾可用選項列表,這是您嘗試執行的極端版本,所以同樣的技巧應該管用。新的FilterChanged事件可用於綁定到可根據需要更新組合框列表項的代碼。在你的原因中,你也可以監聽FilteringComboBox上的DataContextChanged事件。
<DataTemplate x:Key="myTemplateSplitPayeeEdit">
<local:FilteringComboBox Style="{StaticResource GridComboStyle}"
SelectedItem="{Binding PayeeOrTransferCaption, Mode=TwoWay}"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:TransactionsView}}, Path=PayeesAndTransferNames}"
PreviewLostKeyboardFocus="ComboBoxForPayee_PreviewLostKeyboardFocus"
FilterChanged="ComboBoxForPayee_FilterChanged"
>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</local:FilteringComboBox>
</DataTemplate>
private void ComboBoxForPayee_FilterChanged(object sender, RoutedEventArgs e)
{
FilteringComboBox combo = sender as FilteringComboBox;
combo.FilterPredicate = new Predicate<object>((o) => { return o.ToString().IndexOf(combo.Filter, StringComparison.OrdinalIgnoreCase) >= 0; });
}
public class FilteringComboBox : ComboBox
{
public static RoutedEvent FilterChangedEvent = EventManager.RegisterRoutedEvent("FilterChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FilteringComboBox));
public event RoutedEventHandler FilterChanged;
ListCollectionView view;
protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
{
Filter = null;
Items.Filter = null;
this.view = newValue as ListCollectionView;
base.OnItemsSourceChanged(oldValue, newValue);
}
public Predicate<object> FilterPredicate
{
get { return view.Filter; }
set { view.Filter = value; }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
TextBox edit = this.Template.FindName("PART_EditableTextBox", this) as TextBox;
if (edit != null)
{
edit.KeyUp += new System.Windows.Input.KeyEventHandler(OnEditKeyUp);
}
}
void OnEditKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
TextBox box = (TextBox)sender;
string filter = box.Text;
if (string.IsNullOrEmpty(filter))
{
Items.Filter = null;
}
else if (box.SelectionLength < filter.Length)
{
if (box.SelectionStart >= 0)
{
filter = filter.Substring(0, box.SelectionStart);
}
SetFilter(filter);
}
}
public string Filter {
get; set;
}
void SetFilter(string text)
{
Filter = text;
var e = new RoutedEventArgs(FilterChangedEvent);
if (FilterChanged != null)
{
FilterChanged(this, e);
}
RaiseEvent(e);
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
}
}
看來您正在使用WPF。任何解決方案的WinForms? – James