简体   繁体   English

多值ListBox自动选择不需要的项目

[英]Multi value ListBox automatically selects undesired item

I have an object that has some attributes from the list selected - let's say a Promotion that can have 0 to X communication channels. 我有一个对象,该对象具有从列表中选择的一些属性-假设一个促销活动可以具有0到X个通信渠道。 To display/edit this information I am using a listbox with option SelectionMode==MultiExtended. 为了显示/编辑此信息,我使用带有选项SelectionMode == MultiExtended的列表框。

But in some cases it is behaving strangely 但是在某些情况下,它的行为很奇怪

  1. I have Promotion with 2 communication channels selected (first and last out of three channels), 我选择了2个沟通渠道作为促销活动(三个渠道中的第一个和最后一个),

  2. I click on a second channel (that previously was the only unselected channel) and know it shows, that 1st and 2nd channels are selected (I placed a check at the beginning of the listbox SelectedIndexChanged event - and it shows that SelectedItems.Count==2, although I clicked on a single item not holding Ctrl or Shift keys) and in this case SelectedIndexChanged event is triggered twice in all other cases it is triggered just once 我单击第二个通道(以前是唯一未选择的通道),并知道它显示了第一个和第二个通道已选中(我在列表框SelectedIndexChanged事件的开头放置了一个复选框-它显示SelectedItems.Count == 2,尽管我单击了不按住Ctrl或Shift键的单个项目) ,在这种情况下,SelectedIndexChanged事件被触发两次,在所有其他情况下,它仅触发一次

  3. This happens only after the first time I open this dialogform, if I manually select 1st and 3rd item of Channels, and then click on the 2nd item - then it works properly 只有在我第一次打开此对话框窗体之后,如果我手动选择“频道”的第一项和第三项,然后单击第二项,则此情况才会发生-才能正常工作

Screencast of a problem in action 实际存在的问题的屏幕截图

http://screencast.com/t/lVs0e9oau http://screencast.com/t/lVs0e9oau

This is how I load list of all possible channels into listbox 这就是我将所有可能的频道列表加载到列表框中的方式

foreach (var ct in Promotion_operations.Configuration.PromoCommunicationTypes)
{
    KeyValuePair<string, PromotionCommunicationType> nct = 
        new KeyValuePair<string, PromotionCommunicationType>(ct.Name, ct);
    communications.Add(nct);
}
PromotionCommunicationList.DataSource = communications; //Promotion_operations.Configuration.PromoCommunicationTypes;
PromotionCommunicationList.DisplayMember = "Key";
PromotionCommunicationList.ValueMember = "Value";

This is how I load selecteditems based on Promotion's data 这是我根据促销数据加载选定项目的方式

private void LoadSelectedCommunicationsList(ListBox lstbox, List<PromotionCommunication> communications)
{
    lstbox.SelectedItems.Clear();
    foreach (var ct in communications)
    {
        for (int j = 0; j < lstbox.Items.Count; j++)
        {                    
            if (ct.CommunicationType.Id == ((KeyValuePair<string, PromotionCommunicationType>)lstbox.Items[j]).Value.Id)
            {
                lstbox.SelectedItems.Add(lstbox.Items[j]);
            }
        }
    }
}

What could be the cause of this behaviour? 这种行为可能是什么原因?

that clicking on one previously unselected list selects both - newly selected item and first item of the list? 单击一个先前未选择的列表会同时选择-新选择的项目和列表的第一项?

Your PromotionCommunicationList and HistoryCommunicationList are sharing the same reference to your list of objects as DataSource . 您的PromotionCommunicationListHistoryCommunicationListDataSource共享对对象列表的相同引用。 That said, they have the same BindingContext and share the same CurrencyManager . 也就是说,它们具有相同的BindingContext并共享相同的CurrencyManager CurrencyManager is remembering selected items of your ListBox control and that's where your conflict is created because he's saving selected items of both of your ListBoxes . CurrencyManager会记住您ListBox控件的选定项,而这就是您创建冲突的地方,因为他保存了两个ListBoxes选定项。 You already found the solution for your problem because new CurrencyManager is created when you set "different" list (the copy of your original one) as DataSource . 您已经找到解决问题的方法,因为在将“不同”列表(原始列表的副本)设置为DataSource时会创建新的CurrencyManager Another possible solution would be the creation of new BindingContext for one of your ListBox controls. 另一种可能的解决方案是为您的一个ListBox控件创建新的BindingContext
You can try this out: 您可以尝试以下方法:

PromotionCommunicationList.DataSource = communications;
(..)
HistoryCommunicationList.BindingContext = new BindingContext(); // Add this
HistoryCommunicationList.DataSource = communications;

It should solve your problem. 它应该可以解决您的问题。 For more information about BindingContext check this link on MSDN. 有关BindingContext的更多信息,请在MSDN上检查链接。

I found the cause of the problem, though I don't really understand why it caused such a behaviour ( if someone will answer that question, I will accept it as an answer to this question ) 我找到了问题的原因,尽管我并不十分了解为什么会导致这种 问题如果有人回答了这个问题,我会接受它作为对此问题的回答

I had 2 listbox-es in my form and both of them where using the same collection as a Datasource, BUT!!! 我的表单中有2个列表框,两个都使用与数据源相同的集合, 但是!!! SelectedItems was selected using code (acctually it seems that in winforms it is not possible to databind listbox's selecteditems) SelectedItems是使用代码选择的(实际上似乎在winforms中无法对列表框的selecteditems进行数据绑定)

INITIALLY My code was: 最初,我的代码是:

PromotionCommunicationList.DataSource = communications;
(..)
HistoryCommunicationList.DataSource = communications;

Corrected version is: 更正的版本是:

PromotionCommunicationList.DataSource = communications.ToList();
(..)
HistoryCommunicationList.DataSource = communications.ToList();

I know that ToList() makes a copy, but I don't understand what's wrong with having the same collection as DataSource for list items of 2 listbox-es? 我知道ToList()复制了一个副本,但我不明白对于2个listbox-es的列表项,与DataSource具有相同的集合是怎么回事? Why does this have an impact on SelectedItems collection? 为什么这会对SelectedItems集合产生影响?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM