c# - C# WinFrom ComboBox SelectedValueChanged 事件触发延迟
问题描述
更新:
我还没有找到真正的原因,但我发现,更新任何其他数据绑定控件的属性都会引发来自文件夹组合框的“延迟”事件。到目前为止,这不是一个干净的解决方案,但我通过更新未起诉的财产来帮助自己。也就是说,直到我了解真正的原因。
原帖:
我目前正在开发一个 Windows.Forms 项目(不幸的是必须是 WinForms),并且我有三个 ComboBoxes,每个 DataSources 都绑定到一个 List。列表包含文件夹或文件名。每个 Combobox 的 SelectedItem 属性也绑定到一个字符串。SelectedValueChanged 事件已注册并实现。
它们相互依赖,所以当我更新 combobox1 的 DataSource 时,combobox2 的 DataSource 也必须更新。这是因为在 combobox1 中,您可以为随后在 combobox2 中列出的文件选择一个子目录。
现在问题来了。有时会发生,当我以编程方式更新 combobox1 中的 SelectedItem 时,SelectedValueChanged 事件不会立即触发。程序继续,直到combobox2 的DataSource 更新。仅然后,执行组合框 1 的 SelectedValueChanged 事件方法,但不幸的是,它“为时已晚”,因为组合框 2 的数据源已经使用来自组合框 1 的错误子目录进行了更新。
我想了解,哪个事件没有立即触发。下面我发布了相关代码部分的简短示例。
// Cmb1Data and Cmb2Data are the String-Lists which are bound to the DataSource property of the ComboBoxes
// TempCmb1(2)SelectedValue is a string value which contains the value which is to be set.
// Cmb1(2)SelectedValue is a string which is bound the the SelectedItem property of the ComboBoxes
List<string> TempCmb1Data = MainVM.GetCmb1Data();
// some if-statement (plausibility check) is done here before the DataSource is updated.
Cmb1Data = TempCmb1Data ;
if (Cmb1Data.Contains(TempCmb1SelectedValue)
Cmb1SelectedValue = TempCmb1SelectedValue; // This should fire the event - but sometimes it does not...
List<string> TempCmb2Data = MainVM.GetCmb2Data();
// as before, some if-statement (plausibility check) is done here before the DataSource is updated.
Cmb2Data = TempCmb2Data; // This is the point, where the SelectedValueChangedEvent of Combobox1 suddenly is fired, followed by the SelectdValueChanged event of Combobox 2
我已经仔细检查了所有数据绑定和事件方法注册,它们都可以。如果我手动更改 SelectedItem ,一切都运行良好 - 只是有时必须以编程方式完成。
先感谢您。阿尔
编辑:
所以我将代码总结到相关部分(如下所示)。当我测试这段代码以确保它是正确的时,问题并没有发生。在我看来,问题隐藏在其他地方并且不知道在哪里,这里发布的代码太多了。如果发现问题,我将再次深入研究并发布更新。
public partial class Form
{
RuntimeData _RuntimeData = new RuntimeData();
private void Form_Load(object sender, EventArgs e)
{
AddDataBindings();
}
private void AddDataBindings()
{
cmbFolders.DataBindings.Add("SelectedItem", _RuntimeData , "SelectedFolder");
cmbFolders.DataBindings.Add("DataSource", _RuntimeData , "Folders");
cmbFiles.DataBindings.Add("SelectedItem", _RuntimeData , "SelectedFile");
cmbFiles.DataBindings.Add("DataSource", _RuntimeData , "Files");
}
bool _ToggleFlag = false;
private void btTest_Click(object sender, EventArgs e)
{
string TcpString = "Cmd=Execute;Dir=SubDirName1;File=FileName1.dat;";
if (_ToggleFlag)
TcpString = "Cmd=Execute;Dir=SubDirName2;File=FileName2.dat;";
_ToggleFlag = !_ToggleFlag;
// Method is usually executed in separate thread but the problem exists either way. So Threading removed for simplification
ParseAndExecute(TcpString, _RuntimeData);
}
private void ParseAndExecute(string tcpString, RuntimeData runtimeData)
{
if (String.IsNullOrEmpty(tcpString))
return;
string[] Elements = tcpString.Split(new char[] { ';', '=' }, StringSplitOptions.RemoveEmptyEntries);
// Replaced GetFolders-Method for simplification
List<string> TempFolders = new List<string>() { "SubDirName1", "SubDirName2", "SubDirName3" };
if (TempFolders [0] == Elements[3])
;//runtimeData.ProcessFolderChange = true;
runtimeData.Folders.Clear();
runtimeData.Folders = TempFolders;
if (runtimeData.Folders.Contains(Elements[3]))
{
if (runtimeData.Folders[0] != Elements[3])
;//runtimeData.ProcessFolderChange = true;
runtimeData.SelectedFolder = Elements[3];
}
// Replaced GetFiles-Method for simplification
List<string> TempFiles = new List<string>() { "FileName1.dat", "FileName2.dat", "FileName3.dat" };
if (TempFiles [0] == Elements[5])
;//runtimeData.ProcessFileChange = true;
runtimeData.Files.Clear();
runtimeData.Files = TempFiles;
if (runtimeData.Files.Contains(Elements[5]))
{
if (runtimeData.Files[0] != Elements[5])
;//runtimeData.ProcessFileChange = true;
runtimeData.SelectedFile = Elements[5];
}
}
private void cmbFolders_SelectedValueChanged(object sender, EventArgs e)
{
//if (!_RuntimeData.ProcessFolderChange)
//return;
//_RuntimeData.ProcessFolderChange = false;
((ComboBox)sender).DataBindings["SelectedItem"].WriteValue();
_RuntimeData.Files.Clear();
_RuntimeData.Files = new List<string>() { "FileName1.dat", "FileName2.dat", "FileName3.dat" };
}
private void cmbFiles_SelectedValueChanged(object sender, EventArgs e)
{
//if (!_RuntimeData.ProcessFileChange)
//return;
//_RuntimeData.ProcessFileChange= false;
((ComboBox)sender).DataBindings["SelectedItem"].WriteValue();
// do some random stuff with the file...
}
}
// Relevant data from RuntimeData class.
public class RuntimeData : VMBase
{
private List<string> folders = new List<string>() { "SubDirName1", "SubDirName2", "SubDirName3" };
public List<string> Folders
{
get { return folders; }
set
{
folders = value;
OnPropertyChanged(new PropertyChangedEventArgs("Folders"));
}
}
private List<string> files = new List<string>() { "FileName1.dat", "FileName2.dat", "FileName3.dat" };
public List<string> Files
{
get { return files; }
set
{
files = value;
OnPropertyChanged(new PropertyChangedEventArgs("Files"));
}
}
string selectedFolder = String.Empty;
public string SelectedFolder
{
get { return selectedFolder ; }
set
{
selectedFolder = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedFolder"));
}
}
string selectedFile = String.Empty;
public string SelectedFile
{
get { return selectedFile ; }
set
{
selectedFile = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedFile"));
}
}
}
public abstract class VMBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}
解决方案
推荐阅读
- php - Laravel:如何防止试图获取未定义的属性?
- html - CSS 弹性盒属性
- ios - 每个类层次结构中的方法只能挂钩一次
- cmake - qt5 在窗口上使用 cmake 构建:错误:C++11
是必需的,并且缺少或无法编译 - sqlite - SQLite3 按日期连接和分组值
- node.js - Express Rest Api:关于路由的问题?
- sql - 如何获取整列不为空的数据?
- javascript - 异步函数立即在递归函数中调用 then()
- sql-server - 从 XML 中提取多个值并在一行中返回
- amazon-web-services - AWS:有没有办法为 EC2 AutoScaling 使用绝对实例权重容量?