Thursday, March 11, 2010

Combo boxes in WPF

So, I want to give a user a list of PDFs that they can email, in a combo box to make it fit with some existing UI. The PDF data is in a class, so I bind the checkboxes in my template to a property, and it works in both directions. It's working well, that's a great feature in WPF. Except, when I click outside the text of my item, the item is selected, which is fine, but then I added code to set my property so it becomes checked. I've done this, but, no matter what I do, the checked item does not get checked in the actual list, so I open my combobox, and I have an item that is in my list, unchecked, but it's checked in the textbox. If I open the list, and check/uncheck the item in the list, the copy in the textbox stays in synch. It's just when I use code to check it, the UI does not catch up. Seems to me like a case where the two way binding just plain does not work - the same object is rendered in a combobox in two places, and in one place it does not render properly.

Did I mention that intellisense and the list of controls to add to a WPF form all do not work for me in visual studio, I suspect because of the bogus error message I get for every form in my project ?

The solution to this is the following code:

ComboBoxItem itm = PDFList.ItemContainerGenerator.ContainerFromItem(i) as ComboBoxItem;
ContentPresenter myContentPresenter = FindVisualChild(itm);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
CheckBox cb = myDataTemplate.FindName("chkSelect", myContentPresenter) as CheckBox;

if (cb != null)
cb.IsChecked = true;

Simple, right ? But you also need to add this method. You need to add a METHOD to give yourself the reusable ability to find a control inside a template in only 5 lines of code. Insane....

Here's that method

private childItem FindVisualChild(DependencyObject obj) where childItem : DependencyObject
{

for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child != null && child is childItem) return (childItem)child; else { childItem childOfChild = FindVisualChild(child);

if (childOfChild != null)

return childOfChild;

}

}

return null;

}

No comments:

Post a Comment