I'm trying to set the DataContext for my UserControl to the code-behind class of the UserControl. It's really easy to do from the code-behind side:
public partial class OHMDataPage : UserControl
{
public StringList Stuff { get; set; }
public OHMDataPage ()
{
InitializeComponent();
DataContext = this;
}
}
<UserControl 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"
x:Class="LCDHardwareMonitor.Pages.OHMDataPage">
<ScrollViewer>
<ListBox ItemsSource="{Binding Stuff}" />
</ScrollViewer>
</UserControl>
But how can I do this purely from the XAML side and at the UserControl level? It works on child nodes if I do this (and remove DataContext = this;
from the code-behind):
<UserControl 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"
x:Class="LCDHardwareMonitor.Pages.OHMDataPage">
<ScrollViewer
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
<ListBox ItemsSource="{Binding Stuff}" />
</ScrollViewer>
</UserControl>
I'd really like to understand how to do this on the UserControl itself. I expected this to work:
<UserControl 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"
x:Class="LCDHardwareMonitor.Pages.OHMDataPage"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
<ScrollViewer>
<ListBox ItemsSource="{Binding Stuff}" />
</ScrollViewer>
</UserControl>
but it doesn't.
DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}"
Should work.
But if your properties are not set before InitializeComponent()
is called, the WPF binding mechanism doesn't know that your property's values are changed.
To give you a quick idea:
// the binding should work
public StringList Stuff { get; set; }
public Constructor()
{
Stuff = new StringList { "blah", "blah", "foo", "bar" };
InitializeComponent();
}
// the binding won't work
public StringList Stuff { get; set; }
public Constructor()
{
InitializeComponent();
Stuff = new StringList { "blah", "blah", "foo", "bar" };
}
If you're using a list of strings, consider using an ObservableCollection
instead. This will notify the WPF binding mechanism when items are added or removed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With