1

I'm trying to understund how datacontex is passed to usercontrols.

I have 2 classes:

    public class OuterClass
    {
            public InnerClass inner {get; set;}
    }

    public class InnerClass
    {
            public void targetFun()
            {
                    //do something
            }
    }

And the Main Window class

    public class MainWindow: Window
    {
            public OuterClass outer {get; set;}

            //...
    }

In the main window xaml file the DataContext is set to be the Outer class

    <Window <!-- Properties --> >
            <Grid DataContext="{Binding outer}">
                    <MyControl DataContext="{Binding inner}">
                    <!-- Here I do more stuff from outer class -->
            </Grid>
    </Window>

And this would be the definition of my UserControl

    <UserControl x:Class="my:MyControl">
            <Grid>
                    <TextBlock MouseDown="targetFun">Click me!</TextBlock>
            </Grid>
    </UserControl>

When I try to compile I get the error that the function "targetFun" does not exist in 'MyControl' it means that the compiler does not realize im trying to set the context in inner. How do I do that.

Sorry for the simple code I can't show the real one but this is pretty much what i'm doing. Thanks!

Edit: Typo

4
  • your binding path should be outer.inner <MyControl DataContext="{Binding outer.inner}"> Commented Sep 19, 2016 at 18:01
  • It would be nice to be able to bind events to view model methods like that. Commented Sep 19, 2016 at 18:02
  • @IAbstract: that feature isn't built into WPF, but there are ways to accomplish the same thing with attached properties (e.g. "behaviors" or similar extensions to WPF). Commented Sep 19, 2016 at 18:07
  • see e.g. eventtocommandbehavior for the targetfun binding Commented Sep 19, 2016 at 18:08

1 Answer 1

1

In WPF, Binding uses the control's DataContext as its context. For example,

<Grid DataContext="{Binding outer}">
    <local:MyControl DataContext="{Binding inner}">

inner is a member of the value of outer. This example is a little funny because at the time when {Binding inner} is evaluated (or whatever), the DataContext of that Grid is outer, inherited from its parent. But then the binding sets it to something else. I avoid such things; I'm taking your word for it that it works at all.

Anyhow. Where's the binding on MouseDown here?

<TextBlock MouseDown="targetFun">Click me!</TextBlock>

Nowhere. That's not a regular property that you're binding a viewmodel property to, hence the TextBlock's DataContext is irrelevant. That's an event, and are (or should be) giving it an event handler. Events are different (because they are, that's why). Since there's no {Binding ...}, it's not looking for a property of the DataContext; it's looking for an event handler method on the codebehind class. Delete ="targetFun" there, type =" after MouseDown, and it'll prompt you to create an event handler on the codebehind class.

You can call targetFun() like this in the event handler:

private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
    ((sender as FrameworkElement).DataContext as InnerClass)?.targetFun();
}
Sign up to request clarification or add additional context in comments.

2 Comments

You should not be using as here. That operator is useful if you are going to then check the result for null. But you don't. If the object is ever the wrong type, then you'll get a NullReferenceException instead of the diagnostically much more useful InvalidCastException. And of course, if you're sure the object will always be the right type, a direct cast is more appropriate and efficient anyway.
@PeterDuniho It's funny, I just wrote a variant with direct casts, with an explanation of how that was more correct but in this case even more unreadable. I was about to click "Submit" when I realized my explanation needed another revision. At that moment my entire being was overwhelmed by a limitless, indescribable weariness of soul, amounting almost to despair -- and I decided not to bother. You're probably right but this is less unreadable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.