简体   繁体   中英

Setting the DataContext to the current code-behind object in 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM