2011-05-16 9 views
7

Na podstawie niektórych niestandardowych ustawień zabezpieczeń zmieniam formanty podrzędne okna na tylko do odczytu i wyłączone. Aby to osiągnąć, piszę przez elementy podrzędne, gdy okno się ładuje.WPF - Jak wykrywać, kiedy dodawane są nowe elementy potomne?

Działa to dobrze. 99% idealnie.

W moim oknie Mam ItemsControl, którego zawartość jest oparta na ComboBox. Zmień ComboBox, kontrole podrzędne w ItemsControl są ponownie databound. Ale wtedy bezpieczeństwo (tylko do odczytu/wyłączone) nie jest już prawdą.

Zanim przejdziemy do rozwiązania, wiem, że poradziłbym sobie ze zmienionym zdarzeniem ComboBox; ale mam wiele takich skrzynek i nie ma ogólnego rozwiązania, które można zastosować na poziomie okna (think: base) bez względu na to, co moi programiści dodadzą do okna/formularza.

Moje pytanie (przepraszam za długi wątek w) to: jak mogę wykryć, kiedy nowe dziecko zostanie dodane do okna z powodu jakiejś dynamicznej aktywności, takiej jak wiązanie danych? Czy jest wydarzenie NewChildAdded? Czy istnieje zdarzenie DataBindingJustChangedThings?

Coś musi być.

Jeśli twoje rozwiązanie zawiera licznik czasu, nie musisz odpowiadać. Moje formularze są zbyt skomplikowane, aby poradzić sobie z dodatkowym obciążeniem - a opóźnienie między kleszczami jest zbyt realne w kwestii bezpieczeństwa.

Być może myślisz, po prostu zrób zewnętrzny pojemnik tylko do odczytu lub wyłączony. Ma to jednak negatywny wpływ na takie rzeczy jak ekspandery, wielokreskowe pola tekstowe i listy list. Takie podejście nie jest wystarczające. Oczywiście, to jest, gdzie zaczęliśmy iteracje temu.

Jeśli Twoje rozwiązanie zawiera styl, musisz uwzględnić sposób, w jaki mogę nadpisać Twoje podejście na podstawie kontroli. Niektórych kontrolek (takich jak pole wyboru) nie można wyłączyć, ponieważ mają one jakiś cel w układzie interfejsu użytkownika.

Przepraszam za ograniczenia, ale planuję użyć rozwiązania w produkcji.

Dziękuję.

Odpowiedz

18

Czy próbowałeś już OnVisualChildrenChanged?

+0

Niestety, 'OnVisualChildrenChanged' nie wydaje się publicznie dostępnym wydarzeniem dla 'Canvas'. :(Czas na dziedziczenie – IAbstract

+2

Tak na płótno: http://stackoverflow.com/questions/5134080/canvas-in-wpf-how-do-i-detect-when-an-element-has-been-added-removed -z- –

4

Bardzo hacky ale pracował dla mnie, w przypadku, gdy nie dziedziczą z kontrolą, więc nie można przesłonić OnVisualChildrenChanged metody.

Możesz słuchać zdarzenia LayoutUpdated.

Na przykład ryk, chcę słuchać po raz pierwszy moja Siatka, nazwany GridYouWantToListenTo, dodać jeden lub dwa elementy:

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

związany kod:

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