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

sur*_*fen 4 c# wpf xaml mvvm isenabled

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

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

我有3-6不同的SomeGroupIsReadOnly每用户控件的属性(也像大量输入控件TextBox,RadioButtons,ComboBoxes和一些DataGrids),我正在寻找一个通用的,MVVM-友好的解决方案,这将让我重新使用绑定在每个容器而不是分别为每个单独的控件指定它们.

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

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

编辑

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

Dan*_*sha 9

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

XAML:

<GroupBox IsEnabled="{Binding Path=IsGroupEnabled}">
    <StackPanel>
        <Button Content="Sample Button"/>
        <TextBox Text="Sample text box"/>
    </StackPanel>
</GroupBox>
Run Code Online (Sandbox Code Playgroud)

  • +1是的,这有效.但是这也禁用了TextBox,因此用户无法复制内容.我希望TextBox为`IsReadOnly = true`.我编辑了这个问题. (2认同)

Kod*_*hor 6

对我们有用的东西是定义一个代表应用程序权限结构的视图模型(在我下面的例子中为YourPermissionsViewModel).

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

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

<local:PanelExtension IsEnabled="{Binding YourPermissionsViewModel.IsEnabled}" 
                      IsReadOnly="{Binding YourPermissionsViewModel.IsReadOnly}">
    <TextBox Text="eeny" Width="100" />
    <TextBox Text="meeny" Width="100"/>
    <TextBox Text="miny" Width="100"/>
    <TextBox Text="mo" Width="100" />
    <Label Content="coolio" Width="100" />
</local:PanelExtension>
Run Code Online (Sandbox Code Playgroud)

这里是StackPanel扩展控件,包含所有StackPanel的功能,并附加一个自定义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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这种方法,您可以添加所需的自定义属性,它可以为您提供极大的灵活性,并使您能够考虑在必须为各种元素设置复杂权限时可能遇到的众多场景.