Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the DataContext to the current code-behind object in XAML

Tags:

c#

wpf

xaml

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.

like image 657
Adam Avatar asked Feb 04 '15 07:02

Adam


1 Answers

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.

like image 179
DeMama Avatar answered Oct 02 '22 10:10

DeMama