Search code examples
wpfxamluser-controlscommandcommandbinding

Command Binding not working when the host control is added programatically in wpf


This is weird. I have a UserControl (MyControl) with a button inside. I have added a command to this button whose command target is another user control which is again added to the same window.

When I add the UserControl statically in xaml to the CustomControl's host space, the CommandBinding system works fine, where as the same doesn't work if the UserControl is added programatically (on Loaded event of this Window).

What could be the reason. Am I missing something in here ?!?

Update:

*A better representation of my words as an image. Also I have uploaded my source code with binaries @ https://code.google.com/p/commandbindingsample/ and at

http://cid-6fc1e241d4534589.office.live.com/embedicon.aspx/Wpf%20Samples/CommandBinding.zip (not versioned) *

alt text


Solution

  • In your user control, you're setting the CommandBinding like this:

    CommandTarget="{Binding ElementName=userControl11}"
    

    If you look in the Output window while your program's running, you'll see this:

    System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=userControl11'. BindingExpression:(no path); DataItem=null; target element is 'Button' (Name=''); target property is 'CommandTarget' (type 'IInputElement')
    

    This is because there's no element named userControl11 in the current namescope. See this for full details on how XAML namescopes work, but in short, XAML names are only visible within the page, window, or user control that they're declared in. You can't reference a name declared in your window from inside a user control.

    If you want to be able to set a command target on a user control via binding, it needs to be exposed as a dependency property. You'd add a declaration like this to the control:

    public IInputElement CommandTarget
    {
        get { return (IInputElement)GetValue(CommandTargetProperty); }
        set { SetValue(CommandTargetProperty, value); }
    }
    
    public static readonly DependencyProperty CommandTargetProperty =
            DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(UserControl1), new UIPropertyMetadata(null));
    

    and in the user control's XAML, bind to this property:

    <Button Content="Click" 
            Command="local:Commands.ClickCommand" 
            CommandTarget="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=CommandTarget}" />
    

    I can't actually get this to work in your project, but that's because I can't figure your project out. You seem to have two or three user controls named UserControl1 in different namespaces, and the names of the files in the project don't correspond to their contents, and there's not very much in the way of useful commentary. (Just in general, instead of saying "this doesn't work," describe the behavior you're expecting; that makes it a lot clearer to someone trying to help you what your actual problem might be.)

    I hope this is helpful anyway.