WPF container to turn all child controls to read-only

你说的曾经没有我的故事 提交于 2019-12-03 07:07:29

问题


I would like to have a WPF container (panel, user control, etc.) that exposes a property to turn all children to read-only if set. This should pretty much be like setting a parent control to IsEnabled=false, which also disables all children. What children and which of their properties should be considered is fixed (e.g. TextBox.ReadOnly, DataGrid.ReadOnly, ...).

I have tried to create such a control, which essentially iterates all children of the visual tree (recursively) and deals with the controls accordingly.

This works fine, except for the case where further changes would affect the visual tree, so that new children are added. This is true for a ContentControl or ItemsControl. If children are added to the visual tree after I went though them, they obviously are not read-only.

I have bee trying to find a good event to react on (basically detect new children in the visual tree), but was unable to find something appropriate. UpdateLayout is fired, but way to often to go through the visual tree each time.

Is there a way to solve this? Is there probably another approach to getting all (relevant) children recursively set to read-only through a binding on a parent element?

(And no: I would not want to bind all children read-only properties to the global binding instead. The point is to have a single element/part that propagates this to all children)


回答1:


You may do this with an attached property that provides value inheritance:

public class ReadOnlyPanel
{
    public static readonly DependencyProperty IsReadOnlyProperty =
        DependencyProperty.RegisterAttached(
            "IsReadOnly", typeof(bool), typeof(ReadOnlyPanel),
            new FrameworkPropertyMetadata(false,
                FrameworkPropertyMetadataOptions.Inherits, ReadOnlyPropertyChanged));

    public static bool GetIsReadOnly(DependencyObject o)
    {
        return (bool)o.GetValue(IsReadOnlyProperty);
    }

    public static void SetIsReadOnly(DependencyObject o, bool value)
    {
        o.SetValue(IsReadOnlyProperty, value);
    }

    private static void ReadOnlyPropertyChanged(
        DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        if (o is TextBox)
        {
            ((TextBox)o).IsReadOnly = (bool)e.NewValue;
        }
        // other types here
    }
}

You would use it in XAML like this:

<StackPanel local:ReadOnlyPanel.IsReadOnly="{Binding IsChecked, ElementName=cb}">
    <CheckBox x:Name="cb" Content="ReadOnly"/>
    <TextBox Text="Hello"/>
</StackPanel>


来源:https://stackoverflow.com/questions/20357191/wpf-container-to-turn-all-child-controls-to-read-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!