开发者

Binding IsEnabled to the parent ViewModel instead of the UserControl ViewModel

I developed a user control in SilverLight that contains several child controls. Textboxes, ComboB开发者_JAVA技巧oxes 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.


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>


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.


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  


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

Have a look here.

Hope this help !


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜