Is It Possible to Bind Code-Behind Property Without Setting Datacontext?

Is It Possible to Bind Code-Behind Property Without Setting Datacontext?

As titled, I seen couples of similiar question this or this in SO, but I don't see a solution for it.

I know if I need to bind to the code-beind, I need to set Datacontext = this

But my problem is that my datacontext already binding to my ViewModel, but I want to do some UI manipulation with using Command which is defined in the code-beind.

Is it possbile to bind it in xaml? If so, how?

EDIT: I did tried the follows:

<Window x:Class="WpfApplication3.Window1"
xmlns=""
xmlns:x=""
Title="Window1" Height="300" Width="300" x:Name="_Root">
<Grid x:Name="hellogrid">
    <TextBlock x:Name="myTextBlock" Text="AAAA"/>
    <Button Margin="82,119,121,120" Name="button2" Content="{Binding Path=Text, ElementName=myTextBlock}"/>
    <Button Margin="82,72,121,0" Name="button3" Content="{Binding Path=MyText, ElementName=_Root}" Height="23" VerticalAlignment="Top" />
</Grid>

And code-behind:

public partial class Window1 : Window
{
    public string MyText { get; set; }

    public Window1()
    {
        InitializeComponent();
        MyText = "ABC";
    }
}

I could see the Button2 shows AAAA, but Button3 shows nothing....

1

3 Answers

EDIT

The best solution IMO is the one posted by @Saad Imran in this SO question...

With this solution all you have to do is name your window and binding to a property in your XAML will be as easy as this {Binding ElementName=MyWindowName, Path=MyText}

So, what you are doing with Content="{Binding Path=MyText, ElementName=_Root}" is exactly right and your Button Content property IS bound to MyText property but the only thing you are missing is change notification (need to implement INotifyPropertyChanged interface for that) so when you set your MyText property to ABC MyText = "ABC"; no change notification is sent...

Easy way to test this is by setting the MyText property explicitly as such:

private string myText = "ABC";
public string MyText
{
   get { return myText; }
   set { myText = value; }
}

or setting it in the constructor before InitializeComponent() is called:

MyText = "ABC";
InitializeComponent();

If you do that you'll notice that your button will have ABC as its content but changes to MyText property will not affect the button content because there is no change notification...

1

Of course

There are many types of bindings. The most basic one binds to a property on the DataContext, which is usually inherited from a Parent object

<DataTemplate DataType="{x:Type MyModel}">
    <!-- DataContext is object of type MyModel -->
    <local:MyView />
</DataTemplate>

Or

<Window x:Name="MyWindow">
    <!-- DataContext Inherited from Window -->
    <TextBlock Text="{Binding SomeProperty}" /> 
</Window>

where

var SomeObject = new SomeModel();
SomeObject.SomeProperty = "Test";
myWindow.DataContext = SomeObject;

Other binding types include ElementName, where you can specify the target UI element to use as the data source for the binding

<StackPanel>
    <CheckBox x:Name="SomeCheckBox" />
    <TextBlock Text="{Binding ElementName=SomeCheckBox, Path=IsChecked}" />
</StackPanel>

or

<local:MyUserControl x:Name="SomeUserControl">
    <Button Command="{Binding ElementName=SomeUserControl, Path=DataContext.SaveCommand}" />
</local:MyUserControl >

Or RelativeSource, which allows you to find an object relative to the current object to use as a DataSource

<Window Title="Test">
    <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}" />
</Window>

or

<local:MyUserControl>
    <Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=DataContext.SaveCommand}" />
</local:MyUserControl >

And TemplateBinding, which binds is a shortcut to a RelativeSource binding that binds to a templated object

<Button Content="Test">
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <TextBlock Text="{TemplateBinding Content}" />
        </ControlTemplate>
    </Button.Template>
</Button>
4

Sure, you can use ElementName:

<Window Name="root"
        Class="..."
        ...>

    ...

    <TextBox Text="{Binding Path=Foo, ElementName=root}" />

You could also do it with RelativeSource, but the syntax is uglier...

2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sophia Al-Mansoor
Author

Sophia Al-Mansoor

Sophia analyzes international trade, startup ecosystems, retail transformation, and supply chain logistics for modern digital publications.