我正在尝试按照示例WPF Datagrid as Combobox 2
创建自定义组合框我从上面的链接下载了示例项目。然后从Nuget安装了Extended WPF Toolkit,我就可以运行该演示了。但是当我单击组合框中的向下箭头(togglebutton)时,应用程序崩溃,VS2017显示中断模式。
下面是我的ExtendedCombobox类,
public class ExtendedComboBox : ComboBox
{
#region Dependency Properties
public static readonly DependencyProperty PopupContentProperty =
DependencyProperty.Register("PopupContent", typeof(UIElement), typeof(ExtendedComboBox));
public UIElement PopupContent
{
get { return (UIElement)GetValue(PopupContentProperty); }
set { SetValue(PopupContentProperty, value); }
}
#endregion
#region Constructor
static ExtendedComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ExtendedComboBox), new FrameworkPropertyMetadata(typeof(ExtendedComboBox)));
}
#endregion
}
下面是ExtendedDatagridCombobox,
public class ExtendedComboBoxDataGrid : ExtendedComboBox
{
#region Private Fields
private readonly DataGrid _dataGrid;
#endregion
#region Dependency Properties
public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns",
typeof(ObservableCollection<DataGridColumn>), typeof(ExtendedComboBoxDataGrid));
public ObservableCollection<DataGridColumn> Columns
{
get => (ObservableCollection<DataGridColumn>)GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
#endregion
#region Constructors
public ExtendedComboBoxDataGrid()
{
_dataGrid = new DataGrid
{
IsReadOnly = true,
AutoGenerateColumns = false
};
var relativeSource = new RelativeSource(RelativeSourceMode.FindAncestor,
typeof(ExtendedComboBoxDataGrid), 1);
// Bind ItemsSource
var itemsSourceBinding = new Binding("ItemsSource") {RelativeSource = relativeSource};
_dataGrid.SetBinding(ItemsSourceProperty, itemsSourceBinding);
// Bind SelectedItem
Binding selectedItemBinding = new Binding("SelectedItem") {RelativeSource = relativeSource};
_dataGrid.SetBinding(SelectedItemProperty, selectedItemBinding);
_dataGrid.SelectionChanged += DataGrid_SelectionChanged;
PopupContent = _dataGrid;
Columns = new ObservableCollection<DataGridColumn>();
Columns.CollectionChanged += Columns_CollectionChanged;
}
#endregion
#region Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (GetTemplateChild("PART_EditableTextBox") is TextBox editableTbx)
{
editableTbx.TextChanged += EditableTbx_TextChanged;
}
}
#endregion
#region Private Methods
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
IsDropDownOpen = false;
}
private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (DataGridColumn column in e.NewItems)
{
_dataGrid.Columns.Add(column);
}
}
if (e.OldItems != null)
{
foreach (DataGridColumn column in e.OldItems)
{
_dataGrid.Columns.Remove(column);
}
}
}
private void EditableTbx_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox editableTbx = (TextBox)sender;
IsDropDownOpen = true;
_dataGrid.Items.Filter = o =>
{
var properties = o.GetType().GetProperties();
return properties.Select(p => p.GetValue(o, null)).Any(value => value.ToString().ToLower().Contains(editableTbx.Text));
};
}
#endregion
}
下面是我使用控件的xaml,
<Window
x:Class="DemoApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:CustomControls;assembly=CustomControls"
xmlns:local="clr-namespace:DemoApp"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="MainWindow"
Width="300"
Height="300">
<Grid>
<Grid.Resources>
<local:Customers x:Key="Customers" />
</Grid.Resources>
<controls:ExtendedComboBoxDataGrid
Width="250"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsEditable="True"
ItemsSource="{StaticResource Customers}"
SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}},
Path=SelectedCustomer}"
StaysOpenOnEdit="True">
<controls:ExtendedComboBoxDataGrid.Columns>
<toolkit:DataGridTextColumn Binding="{Binding Name}" Header="Name" />
<toolkit:DataGridTextColumn Binding="{Binding Address}" Header="Address" />
<toolkit:DataGridTextColumn Binding="{Binding TelephoneNumber}" Header="Telephone No." />
</controls:ExtendedComboBoxDataGrid.Columns>
<controls:ExtendedComboBoxDataGrid.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="4,0" Text="{Binding Path=Name}" />
<TextBlock Margin="4,0" Text="{Binding Path=Address}" />
<TextBlock Margin="4,0" Text="{Binding Path=TelephoneNumber}" />
</StackPanel>
</DataTemplate>
</controls:ExtendedComboBoxDataGrid.ItemTemplate>
</controls:ExtendedComboBoxDataGrid>
</Grid>
代码背后,
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Customer selectedCustomer;
public Customer SelectedCustomer
{
get
{
return selectedCustomer;
}
set
{
if (object.ReferenceEquals(selectedCustomer, value) != true)
{
selectedCustomer = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SelectedCustomer"));
}
}
}
}
public MainWindow()
{
InitializeComponent();
}
}
点击向下箭头时出现以下错误: 对Automation Peer API的递归调用无效。&#39;
答案 0 :(得分:0)
显然WPF Toolkit控件自动化属性存在一些问题,所以我不得不重写Datagrid控件的OnCreateAutomationPeer()方法。
public class ExtendedDataGrid : DataGrid
{
protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
return null;
}
}