ObservableCollection doesn't get bound to ListBox in codebehind - wpf

I would like to bind a list box to an observable collection in code behind. This is what I am using for the binding:
Binding binding = new Binding();
binding.Source = symTable;
substanceList.SetBinding(ListBox.ItemsSourceProperty, binding);
symTable inherits from ObservableCollection, the Count property gets updated appropriatelly so I know I am adding elements correctly, but the list box isn't. I didn't know what to set the path to, since in XAML it is bound to the whole list.
Note: When adding individual items to the ListBox they get shown, so it is not a display issue. I also tried:
this.Resources.Add("symTable", symTable);
in the window constructor and then this:
but it says the resource cannot be resolved.
I also tried adding it as a resource in XAML but it didn't work again:
//in the window's resources.
<s:SymbolTable x:Key="symTable"/>
...
<ListBox x:Name="substanceList" ItemsSource="{Binding Source={StaticResource symTable}}"/>
and then in code behind:
symTable = (SymbolTable)this.FindResource("symTable");
Does anyone know any other way to do this in code behind or XAML, I think the ElementName refers to objects defined in code behind.
Here is part of the class definition for symTable:
public class SymbolTable : ObservableCollection<Substance>
{
Dictionary<string, Substance> symbolTable;
...
public Substance Insert(Substance s)
{
if (!symbolTable.ContainsKey(s.Name))
{
symbolTable.Add(s.Name, s);
Items.Add(s);
}
return symbolTable[s.Name];
}
Note alright so I just noticed the most weird thing, Items.Add wasn't raising the INotifyChanged event. I used Items.Add in my Insert method, I am guessing that Items.Add doesn't raise a INotifyChanged event so the ListBox wasn't getting updated, but when did Add instead of Items.Add then it worked. Do you know if this is indeed the case?

Ok, following the comments on your question, here is how to declare SymbolTable as resource in XAML and how to bind a ListBox to it. Note the XAML namespace declaration 'local', which refers to the local namespace/assembly, which is named ListBindingTest in my test project.
<Window x:Class="ListBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ListBindingTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:SymbolTable x:Key="symTable"/>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource symTable}}"/>
</Grid>
</Window>
You may access the SymbolTable resource in code behind in your window class like this:
SymbolTable st = (SymbolTable)Resources["symTable"];
st.Add(new Substance());

The DisplayMemberPath needs to be a public property of symTable.

You could always just set the ItemSource directly on the listbox.
substanceList.ItemsSource = symTable;

Related

How can I set ComboBox DataContext in XAML?

I am trying to understand Binding so I have come up with a very simple program to try and test it.
I have the following element in my MainWindow:
<ComboBox Name="comboBox1" ItemsSource="{Binding}" />
In my Code I have the following observable collection:
public ObservableCollection<string> ComboItems = new ObservableCollection<string>();
I can successfully add items this way at any point during runtime:
comboBox1.DataContext = ComboItems;
ComboItems.Clea();
ComboItems.Add("Item");
My question is, how could I set the DataContext in XAML so that I don't have to do it in code? Is it possible?
Thank you!
Something common is:
<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
<ComboBox ItemsSource="{Binding ComboItems}" .../>
However usually you want to inject another object instance as DataContext, have a look at the MVVM pattern for example. Properties in WPF are inherited, so the ComboBox has the DataContext of the Window, it can be overwritten at any level though.
Note: For the Binding to work ComboItems needs to be a public property, not a field.
Resources of interest:
Data Binding Overview
Data Templating Overview
Depedency Properties Overview

WPF Binding dynamic control in code behind to ViewModel

I'm building a custom UserControl in WPF, which has a ViewModel associated. I also want do dynamically make controls in the code behind. But now I'm having problems binding the generated controls with the ViewModel properties. My code is:
<UserControl x:Class="SVT.Teste.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="UserControl1ViewModel">
<Grid Name="GridContainer">
</Grid>
</UserControl>
and code behind:
public UserControl1()
{
InitializeComponent();
System.Windows.Controls.Button newBtn = new Button();
newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
GridContainer.Children.Add(newBtn);
}
public class UserControl1ViewModel
{
private string test = "ola";
public string Test
{
get { return test; }
}
}
When I run this I get:
"System.Windows.Data Error: 40 : BindingExpression path error: 'Test'
property not found on 'object' ''String' (HashCode=-946585093)'.
BindingExpression:Path=Test; DataItem='String' (HashCode=-946585093);
target element is 'Button' (Name=''); target property is 'Content'
(type 'Object')"
Can you help me?
You are setting DataContext property of UserControl1 to a string instead of your view model instance.
You need to do something like this:
<UserControl xmlns:local="clr-namespace:NAMESPACE_WHERE_VIEWMODEL_IS_DEFINED">
<UserControl.DataContext>
<local:UserControl1ViewModel />
</UserControl.DataContext>
<!-- unrelated code omitted -->
</UserControl>
You are setting you DataContext to the type, not an instance that has the properties.
In your method that creates the user control do :
public UserControl1()
{
InitializeComponent();
System.Windows.Controls.Button newBtn = new Button();
newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
GridContainer.Children.Add(newBtn);
**DataContext = new UserControl1ViewModel();**
}
You still have more work to do. The way you have it no notifications or update will happen. Implement the INotifyPropertyChanged interface (on UserControlViewModel). And remove setting DataContext in the XAML to the type.
try with this binding
Binding MyBinding = new Binding();
MyBinding.Path = new PropertyPath("Test");
newBtn.DataContext = new UserControl1ViewModel(); //or MyBinding.Source = new //UserControl1ViewModel();
newBtn.SetBinding(Button.ContentProperty, MyBinding);
max is right, but i have another question. why do you want create your usercontrol dynamic when you have a viemwodel you wanna bind to? makes no sense to me. let me explain:
if you have a viewmodel - you know in mind how this viewmodel should be rendered and what the bindings are. so you could create a usercontrol/view for this viewmodel
MyUserControl1View.xaml
<UserControl>
<Grid>
<Button Content="{Binding Test}"/>
<!-- more controls and binding if the viewmodel expose more-->
</Grid>
</UserControl>
so what you have now is a representation of your viewmodel. they are not connnected but your viewmodel should look like this and the binding are set. till now no datacontext is set at all.
all you have to do now is to go the viewmodel first approach and the use of datatemplates.
let us assume the following in your mainwindow
<Window>
<Window.Resources>
<DataTemplate Datatype="{x:Type local:Usercontrol1viewmodel}">
<view:MyUserControl1View/>
</DataTemplate>
</Window.Resources>
now wpf knows how to render Usercontrol1viewmodel.
one step more in your mainwindow viewmodel you handle your Usercontrol1viewmodel.
public Usercontrol1viewmodel MyWhatEver {get;set;}
if you bind this property to a contentpresenter, you will see the wpf magic;)
<ContentPresenter Content="{Binding MyWhatEver}"/>
now you see the MyUserControl1View in the contentpresenter, no dynamic view code needed. just go with your viewmodels.
ps: feel free to edit my bad english.

Binding from items of an UserControl with custom collection property

This question is a "sequel" to this question (I have applied the answer, but it still won't work).
I'm trying to create an extended ToolBar control for a modular application, which can load its items from multiple data sources (but that is not the issue I'm trying to solve right now, now I want it to work when used as regular ToolBar found in WPF).
In short: I want the ToolBar's items to be able to bind to the tb:ToolBar's parents.
I have following XAML code:
<Window Name="myWindow" DataContext="{Binding ElementName=myWindow}" >
<DockPanel>
<tb:ToolBar Name="toolbar" DockPanel.Dock="Top" DataContext="{Binding ElementName=myWindow}>
<tb:ToolBar.Items>
<tb:ToolBarControl Priority="-3">
<tb:ToolBarControl.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>Maps:</TextBlock>
<ComboBox ItemsSource="{Binding SomeProperty, ElementName=myWindow}">
Some info about the types:
tb:ToolBar is an UserControl with dependency property Items of type FreezableCollection<ToolBarControl>.
tb:ToolBarControl is an UserControl with template pretty much identical to ContentControl's template.
The problem is that the binding in the ComboBox fails (with the usual "Cannot find source for binding with reference"), because its DataContext is null.
Why?
EDIT: The core of the question is "Why is the DataContext not inherited?", without it, the bindings can't work.
EDIT2:
Here is XAML for the tb:ToolBar:
<UserControl ... Name="toolBarControl">
<ToolBarTray>
<ToolBar ItemsSource="{Binding Items, ElementName=toolBarControl}" Name="toolBar" ToolBarTray.IsLocked="True" VerticalAlignment="Top" Height="26">
EDIT 3:
I posted an example of what works and what doesn't: http://pastebin.com/Tyt1Xtvg
Thanks for your answers.
I personally don't like the idea of setting DataContext in controls. I think doing this will somehow break the data context inheritance. Please take a look at this post. I think Simon explained it pretty well.
At least, try removing
DataContext="{Binding ElementName=myWindow}"
from
<tb:ToolBar Name="toolbar" DockPanel.Dock="Top" DataContext="{Binding ElementName=myWindow}>
and see how it goes.
UPDATE
Actually, keep all your existing code (ignore my previous suggestion for a moment), just change
<ComboBox ItemsSource="{Binding SomeProperty, ElementName=myWindow}">
to
<ComboBox ItemsSource="{Binding DataContext.SomeProperty}">
and see if it works.
I think because of the way you structure your controls, the ComboBox is at the same level/scope as the tb:ToolBarControl and the tb:ToolBar. That means they all share the same DataContext, so you don't really need any ElementName binding or RelativeSource binding to try to find its parent/ancestor.
If you remove DataContext="{Binding ElementName=myWindow} from the tb:ToolBar, you can even get rid of the prefix DataContext in the binding. And this is really all you need.
<ComboBox ItemsSource="{Binding SomeProperty}">
UPDATE 2 to answer your Edit 3
This is because your Items collection in your tb:ToolBar usercontrol is just a property. It's not in the logical and visual tree, and I believe ElementName binding uses logical tree.
That's why it is not working.
Add to logical tree
I think to add the Items into the logical tree you need to do two things.
First you need to override the LogicalChildren in your tb:ToolBar usercontrol.
protected override System.Collections.IEnumerator LogicalChildren
{
get
{
if (Items.Count == 0)
{
yield break;
}
foreach (var item in Items)
{
yield return item;
}
}
}
Then whenever you added a new tb:ToolBarControl you need to call
AddLogicalChild(item);
Give it a shot.
This WORKS...
After playing around with it a little bit, I think what I showed you above isn't enough. You will also need to add these ToolBarControls to your main window's name scope to enable ElementName binding. I assume this is how you defined your Items dependency property.
public static DependencyProperty ItemsProperty =
DependencyProperty.Register("Items",
typeof(ToolBarControlCollection),
typeof(ToolBar),
new FrameworkPropertyMetadata(new ToolBarControlCollection(), Callback));
In the callback, it is where you add it to the name scope.
private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var toolbar = (ToolBar)d;
var items = toolbar.Items;
foreach (var item in items)
{
// the panel that contains your ToolBar usercontrol, in the code that you provided it is a DockPanel
var panel = (Panel)toolbar.Parent;
// your main window
var window = panel.Parent;
// add this ToolBarControl to the main window's name scope
NameScope.SetNameScope(item, NameScope.GetNameScope(window));
// ** not needed if you only want ElementName binding **
// this enables bubbling (navigating up) in the visual tree
//toolbar.AddLogicalChild(item);
}
}
Also if you want property inheritance, you will need
// ** not needed if you only want ElementName binding **
// this enables tunneling (navigating down) in the visual tree, e.g. property inheritance
//protected override System.Collections.IEnumerator LogicalChildren
//{
// get
// {
// if (Items.Count == 0)
// {
// yield break;
// }
// foreach (var item in Items)
// {
// yield return item;
// }
// }
//}
I have tested the code and it works fine.
I took the pieces of Xaml that you posted and tried to reproduce your problem.
The DataContext seems to be inheriting just fine from what I can tell. However, ElementName Bindings fail and I think this has to do with the fact that even though you add the ComboBox in the Window, it ends up in a different scope. (It is first added to the Items property of the custom ToolBar and is then populated to the framework ToolBar with a Binding)
A RelativeSource Binding instead of an ElementName Binding seems to be working fine.
But if you really want to use the name of the control in the Binding, then you could check out Dr.WPF's excellent ObjectReference implementation
It would look something like this
<Window ...
tb:ObjectReference.Declaration="{tb:ObjectReference myWindow}">
<!--...-->
<ComboBox ItemsSource="{Binding Path=SomeProperty,
Source={tb:ObjectReference myWindow}}"
I uploaded a small sample project where both RelativeSource and ObjectReference are succesfully used here: https://www.dropbox.com/s/tx5vdqlm8mywgzw/ToolBarTest.zip?dl=0
The custom ToolBar part as I approximated it looks like this in the Window.
ElementName Binding fails but RelativeSource and ObjectReference Bindings work
<Window ...
Name="myWindow"
tb:ObjectReference.Declaration="{tb:ObjectReference myWindow}">
<!--...-->
<tb:ToolBar x:Name="toolbar"
DockPanel.Dock="Top"
DataContext="{Binding ElementName=myWindow}">
<tb:ToolBar.Items>
<tb:ContentControlCollection>
<ContentControl>
<ContentControl.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>Maps:</TextBlock>
<ComboBox ItemsSource="{Binding Path=StringList,
ElementName=myWindow}"
SelectedIndex="0"/>
<ComboBox ItemsSource="{Binding Path=StringList,
Source={tb:ObjectReference myWindow}}"
SelectedIndex="0"/>
<ComboBox ItemsSource="{Binding Path=StringList,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
SelectedIndex="0"/>
</StackPanel>
</ContentControl.Content>
</ContentControl>
</tb:ContentControlCollection>
</tb:ToolBar.Items>
</tb:ToolBar>
Often if there is no DataContext then ElementName will not work either. One thing which you can try if the situation allows it is using x:Reference.
For that you need to move the bound control into the resources of the referenced control, change the binding and use StaticResource in the place where it was, e.g.
<Window Name="myWindow" DataContext="{Binding ElementName=myWindow}" >
<Window.Resources>
<ComboBox x:Key="cb"
ItemsSource="{Binding SomeProperty,
Source={x:Reference myWindow}}"/>
</Window.Resources>
<DockPanel>
<tb:ToolBar Name="toolbar" DockPanel.Dock="Top" DataContext="{Binding ElementName=myWindow}>
<tb:ToolBar.Items>
<tb:ToolBarControl Priority="-3">
<tb:ToolBarControl.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>Maps:</TextBlock>
<StaticResource ResourceKey="cb"/>
The proper answer is probably to add everything to the logical tree as mentioned in previous answers, but the following code has proved to be convenient for me. I can't post all the code I have, but...
Write your own Binding MarkupExtension that gets you back to the root element of your XAML file. This code was not compiled as I hacked up my real code to post this.
[MarkupExtensionReturnType(typeof(object))]
public class RootBindingExtension : MarkupExtension
{
public string Path { get; set; }
public RootElementBinding(string path)
{
Path = path;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
IRootObjectProvider rootObjectProvider =
(IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
Binding binding = new Binding(this.Path);
binding.Source = rootObjectProvider.RootObject;
// Return raw binding if we are in a non-DP object, like a Style
if (service.TargetObject is DependencyObject == false)
return binding;
// Otherwise, return what a normal binding would
object providedValue = binding.ProvideValue(serviceProvider);
return providedValue;
}
}
Usage:
<ComboBox ItemsSource={myBindings:RootBinding DataContext.SomeProperty} />

How do I bind a "list" of strings to a ComboBox in WPF?

I basically want to take a bunch of names in a collection and bind them to a combobox. For example:
Bill
Jack
Bob
Kevin
and have those items in a collection and have it bound to the ComboBox. I'm not sure if the list will be updated dynamically or not, but I prefer to plan for it to be. Any help would be appreciated. I've been trying for a few hours now and can't figure it out. I want to do it in XAML and not the code-behind. In the code-behind,
MyComboBox.ItemsSource = MyObservableCollection;
works fine. I don't know how to do that in XAML though with the collection declared in the code-behind.
Thanks in advance (again), community.
*EDIT:
This is how I have the collection declared and accessible.
public ObservableCollection<string> propertynames
{
get {return _propertynames;}
}
private ObservableCollection<string> _propertynames;
The last thing I tried was this:
<Window.Resources>
<CollectionViewSource Source="{Binding propertynames}" x:Key="srcSort"/>
</Window.Resources>
....
<ComboBox x:Name="cboSort" HorizontalAlignment="Left" VerticalAlignment="Top"
Width="256" Background="WhiteSmoke" Margin="12,50,0,0" FontSize="12pt"
Height="27.28"
SelectedIndex="0"
SelectionChanged="cboWorkCenters_SelectionChanged"
ItemsSource="{Binding Path = {StaticResource srcSort}}">
</ComboBox>
....
I'm a total n00b to this stuff. Been in it about a week now, so I may have done something really obvious to a seasoned user.
*EDIT #2
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:WpfApplication1"
Title="Window1" Height="226" Width="242"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<ComboBox Margin="43,71,40,77"
Name="comboBox1"
ItemsSource="{Binding ob}" />
</Grid>
</Window>
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public ObservableCollection<string> ob
{
get
{
return _ob;
}
}
private ObservableCollection<string> _ob = new ObservableCollection<string>();
public Window1()
{
InitializeComponent();
FillObj();
//comboBox1.ItemsSource = ob;
}
private void FillObj()
{
for (int i = 1; i < 6; i++)
{
_ob.Add(i.ToString());
}
}
}
}
Made above real simple project just to see if I was doing it all wrong. This worked fine so something else must be causing it to fail.
*EDIT #3
*PROBLEM FIXED
For God's sake, I figured it out. I've been on this for HOURS and it's just silly what's caused it to fail.
The solution is this: I wasn't instantiating _propertynames when I declared it. I was querying the class properties with Linq to get the list of properties and then created _propertynames by passing ...GetProperties.ToList<...>() to the constructor. Apparently, you have to instantiate the variable so it hits during InitializeComponent. Unreal.
Once I did that and then added the items to it after the fact, it worked fine.
I wish WPF had a face so I could punch it. I know it's my ignorance of how it works, but I really could have used some kind of message.
Thanks guys for the help. Both of your suggestions were useful once I took care of the root issue.
private ObservableCollection<string> _propertynames
needs to be
private ObservableCollection<string> _propertynames = new ObservableCollection<string>()
There are countless ways of doing this. Once you've created the collection in code-behind, you can:
Call Resources.Add to add it to the window's resource dictionary, and then bind to the resource, e.g. ItemsSource="{Binding {DynamicResource MyList}}".
Give the ComboBox a name (using the x:Name attribute) and set its ItemsSource explicitly in code, e.g. MyComboBox.ItemsSource = myCollection;.
Create a class, make the collection a property of the class, and set the window's DataContext to an instance of that class and bind to it directly, e.g. ItemsSource = "{Binding MyCollectionProperty}".
Make the collection a property of the window, set the window's DataContext to this, and bind to the property (this is essentially the same technique as #3, only you're not creating a new class).
Without setting the window's DataContext, you can still reference a property on it using binding as long as you've given it a name, e.g. {Binding ElementName=MyWindow, Path=MyCollection}. (This is the same as Ross's suggestion.)
Or, without giving the window a name, you can use RelativeSource binding to find the ancestor Window and bind to a property on it. I don't have any confidence in my ability to write a working binding expression that uses RelativeSource off the top of my head, so I'll leave that as an exercise for the reader.
You can set the DataContext of the ComboBox to the instance of your collection, and then set itsItemsSource to {Binding}. You probably wouldn't do this in practice; I mention it just because it seems to be a common mistake for people to set the DataContext of a control without also setting a binding, and then wonder why content from the bound object isn't showing up.
(While I've said "window" in the above, everything I've said is also true for user controls.)
I'm sure there are at least five other ways to do this that I'm not thinking of. Binding is really, really flexible.
What have you tried so far?
I would approach it as follows, assuming the combo box is within a UserControl with a code-behind class containing the public property MyObservableCollection:
<UserControl x:Name="MyCollectionOwnerControl">
<ComboBox ItemsSource="{Binding ElementName=MyCollectionOwnerControl, Path=MyObservableCollection, Mode=OneWay}" />
</UserControl>

WPF How to expose fields on a UserControl

I have a simple application with just a window and a user control. The user control has a list box. The user control is positioned on the Window and I want to bind the user control's listbox to an element on the window's data context.
The examples I've been able to find have CLR properties on the user control which are accessed in code not via XAML.
<Window x:Class="WpfApplication2b.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication2b="clr-namespace:WpfApplication2b" Title="MainWindow" Height="410" Width="520">
<Grid>
<WpfApplication2b:MyUserControl></WpfApplication2b:MyUserControl>
</Grid>
And here is the user control itself.
<UserControl x:Class="WpfApplication2b.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="#FFD8AA13">
<ListBox Height="276" HorizontalAlignment="Left" Margin="12,12,0,0" Name="listBox1" VerticalAlignment="Top" Width="276" />
</Grid>
As you can see it's just a listbox on a different coloured background. I have no idea where to go next :)
I'm guessing that I need to add a code behind property for the list box as a dependency property?
Edit: I've added a dependencyProperty, but I don't think I've quite got the point.
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty ListBoxProperty;
static MyUserControl()
{
FrameworkPropertyMetadata md = new FrameworkPropertyMetadata();
MyUserControl.ListBoxProperty = DependencyProperty.Register("MyListBox", typeof (ListBox),
typeof (MyUserControl), md);
}
public ListBox MyListBox
{
get
{
return (ListBox) GetValue(ListBoxProperty);
}
set
{
SetValue(ListBoxProperty, value);
}
}
public MyUserControl()
{
InitializeComponent();
}
}
Your UserControl will inherit the DataContext from the Window so you can bind properties on the ListBox as though it were declared in the Window. To make the control more flexible you can declare Dependency Properties for the data items from the DataContext that you want to use (i.e. an ItemsSource collection) and pass them into the control, rather than passing the ListBox out.
I think this question/answer is almost what you're looking for. Essentially you're going to need to make a dependency property (using the AddOwner registration method) and set up the DataBinding on the ListBox's ItemsSource to hook to the Dependency Property. The example in the answer does the same thing for a ComboBox, and should be almost the same for a ListBox.
Exposing inner Control properties for binding in WPF

Resources