3

I developed a user control in SilverLight that contains several child controls. Textboxes, ComboBoxes and so on.

The problem is, when I include that UserControl into a parent view and set the complete control to IsEnabled=False, the child controls in that specific UserControl are still enabled.

After all I found the problem.

Adding something like that, implies that the IsEnabled Binding is located in the UserControl binding, not as expected from myself in the DataContext of the parent.

<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
          IsEnabled="{Binding CanModify}" DataContext="{Binding Confidentiality}"/>

QUESTION:
But there's still the question how I can bind the IsEnabled to the ViewModel of the Parent? Because it's not very elegant to copy the CanModify Property to the ViewModel of the Child Control.

Randika Vishman
  • 7,983
  • 3
  • 57
  • 80
BitKFu
  • 3,649
  • 3
  • 28
  • 43

5 Answers5

6

Instead of modifying a binding in some way (for example you can make it dependent on other control name as it is proposed in other answer) I would move separate the control which will be disabled and control where DataContext will be changed. For example:

<ContentControl IsEnabled="{Binding CanModify}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
    <localControls:TeamEmployeeSelector DataContext="{Binding Confidentiality}"/>
</ContentControl>
Snowbear
  • 16,924
  • 3
  • 43
  • 67
  • Hi Snowbear, this seems to be a valid solution. I'll give it a try tomorrow. Thx for the hint. – BitKFu Mar 28 '11 at 14:42
1

Here is how I would do this.

Your TeamEmployeeSelector UserControl will contain a single root level element which by default is a Grid and is given the name "LayoutRoot".

Now you can bind the IsEnabled property of all the child elements to the UserControl like this:-

 <TextBox IsEnabled="{Binding Parent.IsEnabled, ElementName=LayoutRoot}" ... />

By using element-to-element binding you do not need to copy the CanModify property in to child view models.

Some might suggest that you simply add an x:Name to your UserControl element and then bind directly to it rather than going via the Parent property of the root element as I do above. That'll work ok in Silverlight 4 but not in 3 or WP7. Personally I prefer the above.

Randika Vishman
  • 7,983
  • 3
  • 57
  • 80
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • Hi Anothony, I did not try your solution right now, but it does not seem to solve the problem where the CanModify Property must be located. It's not the problem to disable the child controls of the user control, but to disable the usercontrol itself. This UserControl IsEnabled binding depends on the CanModify Property, which indeed must than be located in the viewmodel of the control. That point anoys me ... – BitKFu Mar 28 '11 at 14:41
1

This is a scoping issue. Generally, when creating a UserControl, you want to set itself as the DataContext for its sub-elements. This is most easily accomplished in the constructor:

UserControlExample() {
   InitializeComponent();
   RootElement.DataContext = this;
}

Where RootElement is the name you give to this first child (usually a Grid or panel) of your UserControl.

From here you can set natural bindings for your sub-elements like so:

<TextBox x:Name="MainTextBox" IsEnabled={Binding IsEnabled} />

This works, since TextBox inherits the DataContext of the parent layout panel.

Finally, if you want to have your UserControl's IsEnabled property to be related to its parent, this is best done at the point of declaration:

<Grid>
   <UserControlExample IsEnabled={Binding CanModify} />
</Grid>

This way you keep your concerns separate. The sub-controls don't care what the UserControl is reflecting. They just need to know how to enable/disable when the control's IsEnabled property flips.

sub-controls IsEnabled bound to --> (UserControlExample is DataContext)
   UserControlExample.IsEnabled bound to -->  (VM is DataContext)
      VM.CanModify  
Randika Vishman
  • 7,983
  • 3
  • 57
  • 80
cunningdave
  • 1,470
  • 10
  • 13
0

I don't know if it's possible in Silverlight, but in WPF I would use RelativeSource.

Have a look here.

Hope this help !

Community
  • 1
  • 1
Vivien Ruiz
  • 618
  • 3
  • 11
0
<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="2" IsEnabled="{Binding ElementName=SomeElementName_With_Parent_ViewModel, Path=DataContext.CanModify}" DataContext="{Binding Confidentiality}"/>
Vladimir Dorokhov
  • 3,784
  • 2
  • 23
  • 26