私たちにとってうまくいったことは、アプリケーションの権限構造を表すビュー モデル (以下の例では 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>
次に示すのは、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);
}
}
}
このアプローチを使用すると、カスタマイズされたプロパティを必要な数だけ追加できます。これにより、柔軟性が大幅に向上し、さまざまな要素に複雑なアクセス許可を設定する必要がある場合に遭遇する可能性のある多数のシナリオに対応できます。