2012-04-07 6 views
4

Ich habe eine MVVM Anwendung, die mehrere Ansichten mit einigen komplexen IsReadOnly Regeln basierend auf Benutzerberechtigungen, Ansicht/Bearbeitungsmodus und Objektstatus enthält.Wie setze ich IsReadOnly/IsEnabled auf ganzen Container wie Panel oder GroupBox mit XAML?

Ich möchte IsReadOnly setzen und/oder IsEnabled Eigenschaften für ganze Gruppen von Steuerelementen in dem gleichen Behälter (GroupBox/StackPanel/Grid/UserControl/etc.). Der Wert dieser Eigenschaft wird in ViewModel definiert.

Ich habe 3-6 verschiedene SomeGroupIsReadOnly Eigenschaften pro Usercontrol (mit einer großen Anzahl von Eingabesteuerungen wie TextBox, RadioButtons, ComboBoxes und einig DataGrids) und ich suche nach einer allgemeinen, MVVM -friendly Lösung, dass Wille Erlaube mir, Bindungen pro Container wiederzuverwenden, anstatt sie für jede einzelne Kontrolle separat zu spezifizieren.

Wie kann ich IsReadOnly/IsEnabled auf allen Steuerelementen in Container wie Panel oder GroupBox mit XAML festlegen?

Es scheint nicht, dass WPF diese ...

aus der Box unterstützt

EDIT

ich, dass ein wichtiges Merkmal der Textfelder für einen Container Einstellung IsEnabled vergessen zu erwähnen, deaktiviert - Wesen in der Lage, ihre Inhalte zu kopieren. Ich brauche sie in IsReadOnly=true Zustand. Wenn es dafür einen Workarond gäbe, wäre mein Problem gelöst.

+1

Dies ist die beste Lösung, die ich gefunden habe: http://dkowalski.com/blog/archive/2010/02/04/readonly-wpf-containers.aspx – surfen

Antwort

6

Etwas, das gut für uns gearbeitet hat, ist ein View-Modell zu definieren, die die Berechtigungsstruktur Ihrer Anwendung (YourPermissionsViewModel in meinem Beispiel unten) darstellt.

Dann könnten Sie ein benutzerdefiniertes Panel-Steuerelement erstellen, das jedes Panel Ihrer Wahl erweitert (StackPanel in diesem Beispiel). Auf diese Weise können Sie die IsReadOnly-Eigenschaftsbindungen hinzufügen und sie für die untergeordneten Elemente des Bereichs beibehalten.

Hier ist, was die Platte in XAML aussehen könnte:

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

Und hier ist die Stackpanel Ausschiebesteuerung alle Stackpanel-Funktionen sowie das Anbringen einer benutzerdefinierten IsReadOnly Abhängigkeitseigenschaft enthält, die den entsprechenden Eigenschaftswert auf jeder aktualisiert Kind Kontrollen, die diese Eigenschaft besitzen:

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

Mit diesem Ansatz können Sie so viele maßgeschneiderten Eigenschaften, die Sie benötigen könnten hinzufügen, es verleiht man wirklich ein hohes Maß an Flexibilität und ermöglicht es Ihnen, für eine Rechnung zu tragen Vielzahl von Szenarien, die auftreten können, wenn Sie Ihre komplexen Berechtigungen für verschiedene Elemente festlegen müssen.

+0

Danke für die Antwort, ich mag die Idee der Einkapselung von Berechtigungen in einem 'YourPermissionsViewModel'. Ich werde es versuchen. – surfen

9

Wenn Sie das Panel mit Ihren Steuerelementen deaktivieren, werden auch die Steuerelemente im Panel deaktiviert. Binden Sie das IsEnabled-Element des Bereichs an eine bool-Eigenschaft in Ihrem ViewModel, und legen Sie es entsprechend Ihren Regeln fest, um den Bereich und alle untergeordneten Elemente zu deaktivieren.

XAML:

<GroupBox IsEnabled="{Binding Path=IsGroupEnabled}"> 
    <StackPanel> 
     <Button Content="Sample Button"/> 
     <TextBox Text="Sample text box"/> 
    </StackPanel> 
</GroupBox> 
+2

+1 Ja, das funktioniert. Aber dies hat auch TextBox deaktiviert, so dass der Benutzer den Inhalt nicht kopieren kann. Ich möchte, dass TextBox 'IsReadOnly = true' ist. Ich habe die Frage bearbeitet. – surfen

+0

Ich würde einen invertierten booleschen Konverter erstellen und diesen mit dem IsGroupEnabled-Wert für die Konvertierung an die TextBox binden. Das ist ein guter SO Beitrag dazu: http://stackoverflow.com/questions/1039636/how-to-bind-inverse-boolean-properties-in-wpf – Xcalibur37

Verwandte Themen