0

I am creating user control that will act as container for other control. I found code on StackOverflow and I created user control using that sample. Here is code of my user control.

 <UserControl x:Class="ClassLibrary1.UserControl1"
         xmlns:local="clr-namespace:ClassLibrary1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <UserControl.Template>
    <ControlTemplate>
        <StackPanel>
            <Button Content="Custom Control Text Area 1" IsEnabled="{Binding IsEnabled}"  />
            <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
            <TextBlock Text="Custom Control Text Area 2" />
        </StackPanel>
    </ControlTemplate>
</UserControl.Template>

Code behind is as below

namespace ClassLibrary1
{
   public partial class UserControl1 : UserControl
   {
       public UserControl1()
       {
          InitializeComponent();
       }
   }
}

}

Then I added this user control in other windows application project and added button in this user control so code looks like below

<StackPanel>
    <l:UserControl1>
        <StackPanel >
            <Button Click="Button_Click" Content="Click"/>
            <Button Content="My Control's Content" IsEnabled="{Binding Isbuttonenable}"/>
        </StackPanel>
    </l:UserControl1>

</StackPanel>

Now from my windows application project is working fine and Button control is able to Enable/Disable based on Isbuttonenable valye.

Now I updated User control and added ViewModel to user control. Here is code behind code of user control

namespace ClassLibrary1
{
   public partial class UserControl1 : UserControl
   {
       UserControl1ViewModel model = new UserControl1ViewModel();
       public UserControl1()
       {
          InitializeComponent();
         this.DataContext = model;
       }
    }
} 

Now when I use this updated control in my Windows Application project, data-biding is no longer working. Button is now no longer able to Enble/Disable based on Isbuttonenable value. What may be the solution for this. I want to keep ViewModel in my user control.

I tried lot of way and goggle lot but not able get the solution for this.

  • I experimented many aproaches and nothing worked. Then I found explanation: "TemplateBinding does not support two-way binding, only Binding does that. Even with your BindsTwoWayBeDefault option, it won't support two-way binding." See this http://stackoverflow.com/questions/5913176/in-wpf-why-doesnt-templatebinding-work-where-binding-does – profimedica Sep 07 '15 at 08:27

1 Answers1

1

When you're setting the DataContext of the UserControl from inside its own code that also affects bindings in any usages of that control. Originally your <l:UserControl1> usage had an inherited DataContext which presumably had an Isbuttonenable property, which you were seeing work. When you set a specific value for the DataContext it is the equivalent of changing your XAML to something like this:

<StackPanel>
    <l:UserControl1 DataContext="{StaticResource MyUserControl1ViewModelInstance}">
        <StackPanel >
            <Button Click="Button_Click" Content="Click"/>
            <Button Content="My Control's Content" IsEnabled="{Binding Isbuttonenable}"/>
        </StackPanel>
    </l:UserControl1>

</StackPanel>

Looking at it this way it's pretty obvious that the binding is now going to be looking for an Isbuttonenable property on the UserControl1ViewModel object.

If you want to use an internal VM for your UserControl you'd be better off setting it as a new custom DependencyProperty on UserControl1 and changing those bindings intended to use it to use ElementName or RelativeSource bindings to access that property specifically instead of the implicit DataContext.

I would also recommend rethinking your overall setup here. The prime advantage of a UserControl is that you can set a specific set of content in the UserControl.xaml file and manipulate that in the code-behind or just re-use it as-is. If you're going to be setting the Content externally like this, just use a base ContentControl instance and set up templates to customize it.

John Bowen
  • 24,213
  • 4
  • 58
  • 56