如何使用XAML在整个面板(如Panel或GroupBox)上设置IsReadOnly/IsEnabled? [英] How to set IsReadOnly / IsEnabled on entire container like Panel or GroupBox using XAML?

查看:185
本文介绍了如何使用XAML在整个面板(如Panel或GroupBox)上设置IsReadOnly/IsEnabled?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a MVVM application that contains multiple views with some complex IsReadOnly rules based on user permissions, view/edit mode and object state.

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

I would like to set IsReadOnly and/or IsEnabled properties for entire groups of controls in the same container (GroupBox / StackPanel / Grid / UserControl / etc.). The value of this property will be defined in ViewModel.

每个UserControl我有3-6个不同的SomeGroupIsReadOnly属性(具有大量输入控件,例如TextBoxRadioButtonsComboBoxes和某些DataGrids),我正在寻找一个通用的MVVM友好解决方案,它使我可以在每个容器的基础上重用Binding,而不必为每个单独的控件分别指定它们.

I've got 3-6 different SomeGroupIsReadOnly properties per UserControl (with a large number of input controls like TextBox, RadioButtons, ComboBoxes and some DataGrids) and I'm looking for a generic, MVVM-friendly solution, that will allow me to reuse Bindings on per-container basis, instead of specifying them for each individual control separately.

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

WPF似乎没有开箱即用的支持...

It doesn't seem that WPF supports this out of the box...

编辑

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

I forgot to mention that setting IsEnabled for a container disables an important feature of TextBoxes - being able to copy their contents. I need them to be in IsReadOnly=true state. If there was a workarond for that, then my problem would be solved.

推荐答案

对我们来说行之有效的方法是定义一个表示您的应用程序的权限结构的视图模型(在下面的示例中为YOURPermissionsViewModel).

Something that's worked well for us is to define a view model that represents the permission structure of your application (YourPermissionsViewModel in my example below).

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

Then you could create a custom panel control that extends any panel of your choice (StackPanel in this example). That way you can add in the IsReadOnly property bindings and persist them to the panel's children.

这是XAML中的面板的外观:

Here's what the panel in XAML could look like:

<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>

这是StackPanel扩展控件,其中包含StackPanel的所有功能,并附加了自定义的IsReadOnly依赖项属性,该属性会在拥有该属性的任何子控件上更新相应的属性值:

And here is the StackPanel extension control containing all of StackPanel's features as well as attaching a custom IsReadOnly dependency property that updates the corresponding property value on any child controls who possess that property:

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);
        }
    }
}

使用这种方法,您可以添加所需的许多自定义属性,它确实为您带来了极大的灵活性,并使您能够解决必须对各种元素设置复杂权限时可能遇到的多种情况.

With this approach you could add as many customized properties you need, it really lends you a great deal of flexibility and enables you to account for a multitude of scenarios you might encounter when you have to set your complex permissions on various elements.

这篇关于如何使用XAML在整个面板(如Panel或GroupBox)上设置IsReadOnly/IsEnabled?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆