I'm having trouble getting a binding to work. I have created a completely fruitless example to demonstrate my problem. It goes like this...
I have a collection of widgets that I want to be able to define in XAML. This collection will be associated with a UserControl. In the XAML I want to bind the 'Name' property of the widgets to bits of data (strings in this example).
So, for code I have a Widget class that derives from DependencyObject
public class Widget : DependencyObject
{
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
// Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(Widget), new UIPropertyMetadata("--widget--"));
}
Notice the default value for this property is "--widget--". I also have a WidgetCollection class...
public class WidgetCollection : Collection<Widget>
{
public WidgetCollection()
{
}
}
The WidgetControl is the parent of a WidgetCollection that it exposes as a property named 'Widgets'
[ContentPropertyAttribute("Widgets")]
public partial class WidgetControl : UserControl
{
public WidgetCollection Widgets
{
get { return (WidgetCollection)GetValue(WidgetsProperty); }
set { SetValue(WidgetsProperty, value); }
}
// Using a DependencyProperty as the backing store for Widgets. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WidgetsProperty =
DependencyProperty.Register("Widgets", typeof(WidgetCollection), typeof(WidgetControl), new UIPropertyMetadata(null));
public WidgetControl()
{
Widgets = new WidgetCollection();
InitializeComponent();
}
public IEnumerable<string> GetWidgetNames()
{
return Widgets.Select(w => w.Name);
}
}
For visual feedback, the WidgetControl displays a red rectangle...
<UserControl x:Class="StackOverflow.BindingProblem.WidgetControl"
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>
<Rectangle Margin="0" Fill="Red"/>
</Grid>
</UserControl>
So now that I've got all the pieces for my demo, I'll put them together in the MainWindow...
<Window x:Class="StackOverflow.BindingProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:StackOverflow.BindingProblem"
Title="MainWindow" Height="220" Width="160"
x:Name="x_win">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<l:WidgetControl x:Name="x_WidgetControl" Grid.Row="0">
<l:Widget Name="Sprocket"/>
<l:Widget Name="{Binding Path=WidgetName1, ElementName=x_win}"/>
<l:Widget Name="{Binding Path=WidgetName2, ElementName=x_win}"/>
<l:Widget Name="Wrench"/>
</l:WidgetControl>
<StackPanel Orientation="Vertical" Grid.Row="1">
<TextBlock Text="Sprocket"/>
<TextBlock Text="{Binding Path=WidgetName1, ElementName=x_win}"/>
<TextBlock Text="{Binding Path=WidgetName2, ElementName=x_win}"/>
<TextBlock Text="Wrench"/>
</StackPanel>
<ListBox x:Name="x_ListBox" Grid.Row="2"/>
</Grid>
</Window>
Here, I've dumped the results to the window so you can see what I'm talking about without having to use a debugger. I'm using a grid to create three rows. The top shows the WidgetControl (an exciting red rectangle!) to which I'm defining 4 widgets in the XAML. Note that two of the widgets have hard-coded names and the other two have names data-bound to string properties defined on the MainWindow class. The middle row shows four TextBlocks that have the exact same bindings. The bottom row shows a listbox. This listbox is populated with the names of the widgets in the WidgetCollection owned by the WidgetControl. This list is gathered AFTER the window is loaded, and thus after the data binding is complete.
The MainWindow code behind looks like this ...
public partial class MainWindow : Window
{
public MainWindow()
{
Loaded += new RoutedEventHandler(MainWindow_Loaded);
InitializeComponent();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
x_ListBox.ItemsSource = x_WidgetControl.GetWidgetNames();
}
public string WidgetName1
{
get { return "Crank"; }
}
public string WidgetName2
{
get { return "Wheel"; }
}
}
When this demo runs, the window looks like this...
[rats! picture ommitted because I'm a new submitter] I'll mock it up with text...
-----------
| |
| | <-- red rectangle (the WidgetControl)
| |
-----------
Sprocket
Crank <-- textblocks
Wheel
Wrench
-----------
Sprocket
--widget-- <-- listbox
--widget--
Wrench
-----------
Note how the bindings on the TextBlocks work fine, but the bindings on the Widgets don't. The bottom row shows the unsuccessful bindings as --widget-- instead of Crank and Wheel.
So why does this happen and how can I get the bindings to work?