如何使用XAML在整个容器(如Panel或GroupBox)上设置IsReadOnly / IsEnabled?

我有一个MVVM应用程序,它包含多个视图,其中包含一些基于用户权限,查看/编辑模式和对象状态的复杂IsReadOnly规则。

我想为同一容器中的整个控件组设置IsReadOnly和/或IsEnabled属性( GroupBox / StackPanel / Grid / UserControl /等)。 此属性的值将在ViewModel中定义。

每个UserControl我有3-6个不同的SomeGroupIsReadOnly属性(有大量的输入控件,如TextBoxRadioButtonsComboBoxes和一些DataGrids ),我正在寻找一个通用的, MVVM友好的解决方案,这将允许我重用基于每个容器的绑定,而不是单独为每个单独的控件指定它们。

如何使用XAML在Panel或GroupBox等容器内的所有控件上设置IsReadOnly / IsEnabled?

WPF似乎不支持这种开箱即用的…

编辑

我忘了提到为容器设置IsEnabled会禁用TextBoxes的一个重要function – 能够复制其内容。 我需要它们处于IsReadOnly=true状态。 如果有一个工作方法,那么我的问题将得到解决。

对我们来说效果很好的东西是定义一个代表应用程序权限结构的视图模型(我的示例中的YourPermissionsViewModel)。

然后,您可以创建一个自定义面板控件,扩展您选择的任何面板(本例中为StackPanel)。 这样,您可以添加IsReadOnly属性绑定并将它们持久保存到面板的子项中。

这是XAML中的面板可能是这样的:

        

这里是StackPanel扩展控件,包含StackPanel的所有function,以及附加自定义IsReadOnly依赖项属性,该属性更新拥有该属性的任何子控件的相应属性值:

 public class PanelExtension : StackPanel { public bool IsReadOnly { get { return (bool)GetValue(IsReadOnlyProperty); } set { SetValue(IsReadOnlyProperty, value); } } public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(PanelExtension), new PropertyMetadata(new PropertyChangedCallback(OnIsReadOnlyChanged))); private static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((PanelExtension)d).OnIsReadOnlyChanged(e); } protected virtual void OnIsReadOnlyChanged(DependencyPropertyChangedEventArgs e) { this.SetIsEnabledOfChildren(); } public PanelExtension() { this.Loaded += new RoutedEventHandler(PanelExtension_Loaded); } void PanelExtension_Loaded(object sender, RoutedEventArgs e) { this.SetIsEnabledOfChildren(); } private void SetIsEnabledOfChildren() { foreach (UIElement child in this.Children) { var readOnlyProperty = child.GetType().GetProperties().Where(prop => prop.Name.Equals("IsReadOnly")).FirstOrDefault(); readOnlyProperty.SetValue(child, this.IsReadOnly, null); } } } 

使用这种方法,您可以添加所需的任意数量的自定义属性,它确实为您提供了极大的灵活性,使您能够考虑在必须为各种元素设置复杂权限时可能遇到的多种情况。

禁用包含控件的Panel也将禁用Panel内的控件。 将Panel的IsEnabled成员绑定到ViewModel上的bool属性,并根据您的规则进行设置以禁用Panel及其所有子项。

XAML: