将 IsEnabled 绑定到父 ViewModel 而不是 UserControl ViewModel
Posted
技术标签:
【中文标题】将 IsEnabled 绑定到父 ViewModel 而不是 UserControl ViewModel【英文标题】:Binding IsEnabled to the parent ViewModel instead of the UserControl ViewModel 【发布时间】:2011-07-19 12:26:47 【问题描述】:我在 SilverLight 中开发了一个包含多个子控件的用户控件。 Textboxes
、ComboBoxes
等等。
问题是,当我将 UserControl
包含到父视图中并将完整控件设置为 IsEnabled=False
时,该特定 UserControl
中的子控件仍处于启用状态。
毕竟我发现了问题。
添加类似的内容意味着IsEnabled
绑定位于UserControl
绑定中,而不是像我预期的那样位于父级的DataContext
中。
<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
IsEnabled="Binding CanModify" DataContext="Binding Confidentiality"/>
问题:
但是还有一个问题,我如何将IsEnabled
绑定到父视图模型?因为将CanModify
属性复制到子控件的ViewModel中不是很优雅。
【问题讨论】:
【参考方案1】:我不知道在 Silverlight 中是否可行,但在 WPF 中我会使用 RelativeSource。
看看here。
希望有帮助!
【讨论】:
【参考方案2】:<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="2" IsEnabled="Binding ElementName=SomeElementName_With_Parent_ViewModel, Path=DataContext.CanModify" DataContext="Binding Confidentiality"/>
【讨论】:
【参考方案3】:不是以某种方式修改绑定(例如,您可以使其依赖于其他答案中建议的其他控件名称),我将单独移动将被禁用的控件并控制DataContext
将被更改的位置.例如:
<ContentControl IsEnabled="Binding CanModify" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<localControls:TeamEmployeeSelector DataContext="Binding Confidentiality"/>
</ContentControl>
【讨论】:
嗨雪熊,这似乎是一个有效的解决方案。我明天试试。谢谢提示。【参考方案4】:我会这样做。
您的 TeamEmployeeSelector
UserControl
将包含一个根级元素,默认情况下为 Grid
并命名为“LayoutRoot”。
现在您可以将所有子元素的IsEnabled
属性绑定到UserControl
,如下所示:-
<TextBox IsEnabled="Binding Parent.IsEnabled, ElementName=LayoutRoot" ... />
通过使用元素到元素绑定,您无需将CanModify
属性复制到子视图模型中。
有些人可能会建议您只需将 x:Name
添加到您的 UserControl 元素,然后直接绑定到它,而不是像上面那样通过根元素的 Parent
属性。这在 Silverlight 4 中可以正常工作,但在 3 或 WP7 中不行。我个人更喜欢上面的。
【讨论】:
您好 Anothony,我现在没有尝试您的解决方案,但它似乎无法解决必须定位 CanModify 属性的问题。禁用用户控件的子控件不是问题,而是禁用用户控件本身。此 UserControl IsEnabled 绑定取决于 CanModify 属性,该属性实际上必须位于控件的视图模型中。这点让我很恼火......【参考方案5】:这是一个范围界定问题。通常,在创建UserControl
时,您希望将其自身设置为其子元素的DataContext
。这在构造函数中最容易实现:
UserControlExample()
InitializeComponent();
RootElement.DataContext = this;
其中RootElement
是您给UserControl
的第一个孩子(通常是网格或面板)的名称。
您可以从这里为您的子元素设置自然绑定,如下所示:
<TextBox x:Name="MainTextBox" IsEnabled=Binding IsEnabled />
这是可行的,因为TextBox
继承了父布局面板的DataContext
。
最后,如果您想让UserControl
的IsEnabled
属性与其父级相关联,最好在声明时完成:
<Grid>
<UserControlExample IsEnabled=Binding CanModify />
</Grid>
这样您就可以将您的顾虑分开。子控件不关心UserControl
反映的内容。他们只需要知道当控件的IsEnabled
属性翻转时如何启用/禁用。
sub-controls IsEnabled bound to --> (UserControlExample is DataContext)
UserControlExample.IsEnabled bound to --> (VM is DataContext)
VM.CanModify
【讨论】:
以上是关于将 IsEnabled 绑定到父 ViewModel 而不是 UserControl ViewModel的主要内容,如果未能解决你的问题,请参考以下文章
如何将 WPF ListBoxItem 的 IsEnabled 属性绑定到其源项的属性?
WPF 条件绑定。 Button.IsEnabled 到 SelectedIndex >= 0
将 UserControl ListBox ItemSsource 绑定到父 DataContext 时出错