2011-05-16 8 views
7

En función de algunas configuraciones de seguridad personalizadas, modifico los controles secundarios de ventana para que sean de solo lectura y deshabilitados. Para lograr esto, recorro los controles secundarios cuando se carga la ventana.WPF - ¿Cómo detectar cuando se agregan nuevos elementos secundarios de Visual?

Esto funciona bien. 99% perfecto.

En mi ventana tengo un ItemsControl cuyo contenido se basa en un ComboBox. Cambie el ComboBox, los controles secundarios en ItemsControl están enlazados de nuevo. Pero, entonces la seguridad (readonly/disabled) ya no es verdad.

Antes de saltar a la solución, sé que podría manejar el evento cambiado ComboBox; pero, tengo muchos de esos cuadros y una solución genérica para aplicar a nivel de ventana (pensar: base) sin importar lo que mis desarrolladores agreguen a la ventana/formulario.

Mi pregunta (lo siento por la larga anticipación) es, ¿cómo puedo detectar cuando un niño nuevo se agrega a la ventana debido a alguna actividad dinámica como la vinculación de datos? ¿Hay algún evento NewChildAdded? ¿Hay un evento DataBindingJustChangedThings?

Tiene que haber algo.

Si su solución incluye un temporizador, no necesita responder. Mis formularios son demasiado complejos para manejar esa carga adicional, y la demora entre los tics es demasiado real como un problema de seguridad.

Usted podría estar pensando, simplemente haga que el contenedor exterior sea de solo lectura o deshabilitado. Pero esto tiene un efecto negativo en cosas como expansores, cuadros de texto multilínea y cuadros de lista. Tal enfoque no es lo suficientemente granular. Por supuesto, es donde comenzamos iteraciones atrás.

Si su solución incluye un estilo, debe incluir cómo puedo anular su enfoque por cada control. Algunos controles (como una casilla de verificación) no se pueden desactivar ya que tienen un propósito en el diseño de la interfaz de usuario.

Disculpe las limitaciones, pero planeo usar la solución en producción.

Gracias.

Respuesta

18

¿Has probado OnVisualChildrenChanged?

+0

Desafortunadamente, 'OnVisualChildrenChanged' no parece ser un evento de acceso público para 'Canvas'. :(Hora de heredar. – IAbstract

+2

Sí para Canvas: http://stackoverflow.com/questions/5134080/canvas-in-wpf-how-do-i-detect-when-an-element-has-been-added-removed -desde el –

4

poco limpia, pero funcionó para mí, en caso de que no heredan desde el control por lo que no puede reemplazar el OnVisualChildrenChanged método.

Puede escuchar el evento LayoutUpdated.

En el ejemplo que sigue, quiero escuchar la primera vez que mi rejilla, llamada GridYouWantToListenTo, añadir uno o dos elementos:

Código
<Window x:Class="WpfApplication23.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication23" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid x:Name="GridYouWantToListenTo"> 
    </Grid> 
</Window> 

atrás:

using System; 
using System.Linq; 
using System.Windows; 

namespace WpfApplication23 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      GridYouWantToListenTo.LayoutUpdated += GridYouWantToListenTo_LayoutUpdated; 
     } 

     private int _lastNumbreOfGridChildren = 0; 
     private void GridYouWantToListenTo_LayoutUpdated(object sender, EventArgs e) 
     { 
      var children = GridYouWantToListenTo 
        ?.Children 
        ?.OfType<FrameworkElement>() ?? Enumerable.Empty<FrameworkElement>(); 

      if (!children.Any()) 
      { 
       _lastNumbreOfGridChildren = 0; 
      } 

      int currentNumberOfItems = children.Count(); 

      if (_lastNumbreOfGridChildren == 0 && currentNumberOfItems == 1) 
      { 
       //Your Logic 
      } 
      else if (_lastNumbreOfGridChildren == 0 && currentNumberOfItems == 2) 
      { 
       //Your Logic 
      } 
     } 
    } 
} 
Cuestiones relacionadas