【发布时间】:2022-02-05 02:21:37
【问题描述】:
在我的 WPF 窗口应用程序中,我有一个组合框,该组合框在应用程序启动时填充,我还想为组合框启用建议附加类型功能 (using this)。但是当我尝试在组合框上输入一些内容时,我得到了错误:System.InvalidOperationException: Items collection must be empty before using ItemsSource.
我该如何摆脱它?我想从下拉列表中选择或开始在组合框中输入,然后在窗口加载时从那里选择项目。
public partial class Window1 : Window
{
List<string> Names= new List<string>();
int lastRow = 0;
string file_Bills=@"BILLS.xlsx";
string file_CNDN=@"CN_DN.xlsx";
string file_supp=@"suppliers.xlsx";
public Window1()
{
InitializeComponent();
ExcelPackage.LicenseContext =LicenseContext.NonCommercial;
FillCombo();
}
public List<string> FillCombo()
{
using (ExcelPackage package = new ExcelPackage(new System.IO.FileInfo(file_Bills), false))
{
ExcelWorksheet mainSheet = package.Workbook.Worksheets.First();
for (int i = 2; i <= mainSheet.Dimension.End.Row; i++)
{
if (!string.IsNullOrEmpty(mainSheet.Cells["A"+i].Text))
{
lastRow =i;
}
}
List<string> party = new List<string>();
for (int row = 2; row <= lastRow; row++)
{
if (!string.IsNullOrEmpty(mainSheet.Cells[row, 1].Text))
{
party.Add(mainSheet.Cells[row, 1].Text);
}
}
foreach (var element in party.OrderBy(a=>a.ToLowerInvariant()).Distinct())
{
cmb.Items.Add(element);
Names.Add(element);
}
}
return Names;
}
//portion implementing the suggestappend like feature
public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
private void PreviewTextInput_EnhanceComboSearch(object sender, TextCompositionEventArgs e)
{
ComboBox cmb = (ComboBox)sender;
cmb.IsDropDownOpen = true;
if (!string.IsNullOrEmpty(cmb.Text))
{
string fullText = cmb.Text.Insert(GetChildOfType<TextBox>(cmb).CaretIndex, e.Text);
cmb.ItemsSource = Names.Where(s => s.IndexOf(fullText, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else if (!string.IsNullOrEmpty(e.Text))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(e.Text, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}
private void Pasting_EnhanceComboSearch(object sender, DataObjectPastingEventArgs e)
{
ComboBox cmb = (ComboBox)sender;
cmb.IsDropDownOpen = true;
string pastedText = (string)e.DataObject.GetData(typeof(string));
string fullText = cmb.Text.Insert(GetChildOfType<TextBox>(cmb).CaretIndex, pastedText);
if (!string.IsNullOrEmpty(fullText))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(fullText, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}
private void PreviewKeyUp_EnhanceComboSearch(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back || e.Key == Key.Delete)
{
ComboBox cmb = (ComboBox)sender;
cmb.IsDropDownOpen = true;
if (!string.IsNullOrEmpty(cmb.Text))
{
cmb.ItemsSource = Names.Where(s => s.IndexOf(cmb.Text, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
}
else
{
cmb.ItemsSource = Names;
}
}
}
}
XAML:
<ComboBox
IsTextSearchEnabled="False"
PreviewTextInput="PreviewTextInput_EnhanceComboSearch"
PreviewKeyUp="PreviewKeyUp_EnhanceComboSearch"
DataObject.Pasting="Pasting_EnhanceComboSearch"
IsEditable="True"
Name="cmb"
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
FontFamily="Segoe UI"
FontStyle="Normal"
FontSize="18"
Margin="10 10 10 0"
Height="35"
MaxHeight="40"
Width="300"
MaxWidth="450" />
【问题讨论】:
-
正如错误所说,您直接在
FillCombo中添加项目,然后您想分配ItemsSource不能同时拥有...所以要么在添加之前清除项目,新元素,或者您有一个绑定集合(搜索:WPF 组合框绑定),然后操作该集合。一般来说,这种方法非常“WinForms”-ish.... WPF 的工作方式不同 -
@dba 我不打算让它成为一个 MVVM 应用程序,我也不打算在未来做任何事情,这只是一个简单的应用程序,所以还有其他方法可以做到这一点吗?顺便说一句,我是 WPF 的新手(来自 WinForms),这就是为什么我的方法非常“WinForms”-ish :)
-
是的,我是这么认为的 :-) 但是成功切换到 WPF 也意味着调整您的编码/工作流程......无论如何,如果您直接添加
Items,则不能使用ItemsSource...坚持操纵Items(清除(),添加()等) -
@dba 所以基本上你是说建议附加类型功能代码的整个部分(所有方法)需要修改吗?哇,你能帮忙吗?