私がやったことは、 ListBox をすべて一緒に放棄することでした. TreeViewに落ち着きました。
その前に、現在のアイテムを選択するためにこの関数を作成し、Page_PreRender から呼び出しました。これは、バインディングが完了したためであり、必要なコントロールを取得できました。
protected void SelectCategories()
{
ListBox lb = (ListBox)fvProduct.FindControl("lstCategory");
Product product = (Product)pdc.Products.Where(a => a.Sku == txtSku.Text).FirstOrDefault();
var c = pdc.ProductCategories.Where(b => b.ProductId == product.ProductId);
if (lb != null && lb.Items.Count > 0)
{
foreach (ProductCategory cat in c)
{
foreach (ListItem li in lb.Items)
{
if (cat.CategoryId == Convert.ToInt32(li.Value))
{
li.Selected = true;
}
}
}
}
}
そして、ListBox から更新する必要があるときは、FormView.ItemUpdating イベントから次のコードを呼び出しました。
protected void UpdateCategories()
{
ListBox lb = (ListBox)fvProduct.FindControl("lstCategory");
Product product = (Product)pdc.Products.Where(a => a.Sku == txtSku.Text).FirstOrDefault();
if (lb != null && lb.Items.Count > 0)
{
foreach (ListItem li in lb.Items)
{
ProductCategory pc = new ProductCategory();
pc = (ProductCategory)pdc.ProductCategories.Where(d => d.CategoryId == Convert.ToInt32(li.Value) && d.ProductId == product.ProductId).FirstOrDefault();
if (pc == null)
{
if (li.Selected == true)
{
//note: if li is selected but pc is null then insert new record .
pc = new ProductCategory();
pc.ProductId = product.ProductId;
pc.CategoryId = Convert.ToInt32(li.Value);
pdc.ProductCategories.InsertOnSubmit(pc);
pdc.SubmitChanges();
}
}
else
{
if (li.Selected == false)
{
//note: if li is not selected but pc is not null then remove record.
pdc.ProductCategories.DeleteOnSubmit(pc);
pdc.SubmitChanges();
}
}
}
}
}
これはパフォーマンス的には非常に悪いものでしたが、うまくいきました。linq queryをコンパイルすれば改善できたかもしれませんが、そこまでは行きませんでした。上記のコメントから、問題に対する独自の回避策を見つけた可能性があることを理解しています。そのため、私のような将来の失われた魂を助ける可能性がある場合にのみ、この回答を追加しています.
結局、TreeView は私にとってより良いツールだったので、とにかくこれを行う必要はありませんでした。TreeView を LinqDataSource に簡単にバインドできないため、新しい冒険が始まりましたが、それは別の日の話です。