2010-08-19 6 views
3

J'utilise une liaison de formeReliure à Children.Count

{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=Rows} 

Malgré l'ajout des enfants en XAML, quand je casse dans le convertisseur, la valeur est toujours 0.

Ce que je suppose que se passe est que les enfants ne sont pas ajoutés jusqu'à ce que cette liaison est appelée. Je suppose aussi que la liaison est cassée après avoir été appelée une fois parce que .Count est une propriété en lecture seule (j'ai déjà eu un problème similaire où j'ai dû ajouter un setter vide dans la propriété pour maintenir la liaison et le fou WPF) d'où la liaison ne se met pas à jour une fois que les enfants sont ajoutés.

Cependant, je suis coincé sur le peu d'où vous venez avec une solution pour le problème et le faire fonctionner ... =/

<UniformGrid x:Name="MyUniformGrid" 
    Rows="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=R}" 
    Columns="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=C}"> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    </UniformGrid> 

Merci, Rabit

Répondre

8

C'est parce que UIElementCollection (le type de propriété Children) ne soulève pas de notifications lorsqu'un nouvel élément est ajouté ou supprimé, de sorte que la liaison n'est pas rafraîchi

Vous pouvez cependant créer votre propre coutume UniformGrid et o verride la propriété CreateUIElementCollection pour créer une instance d'une collection personnalisée qui hérite UIElementCollection et implémente INotifyCollectionChanged.

Voici une implémentation de base:

ObservableUIElementCollection

public class ObservableUIElementCollection : UIElementCollection, INotifyCollectionChanged, INotifyPropertyChanged 
{ 
    public ObservableUIElementCollection(UIElement visualParent, FrameworkElement logicalParent) 
     : base(visualParent, logicalParent) 
    { 
    } 

    public override int Add(UIElement element) 
    { 
     int index = base.Add(element); 
     var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index); 
     OnCollectionChanged(args); 
     OnPropertyChanged("Count"); 
     OnPropertyChanged("Item[]"); 
     return index; 
    } 

    public override void Clear() 
    { 
     base.Clear(); 
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     OnPropertyChanged("Count"); 
     OnPropertyChanged("Item[]"); 
    } 

    public override void Insert(int index, UIElement element) 
    { 
     base.Insert(index, element); 
     var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index); 
     OnCollectionChanged(args); 
     OnPropertyChanged("Count"); 
     OnPropertyChanged("Item[]"); 
    } 

    public override void Remove(UIElement element) 
    { 
     int index = IndexOf(element); 
     if (index >= 0) 
     { 
      RemoveAt(index); 
      var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, element, index); 
      OnCollectionChanged(args); 
      OnPropertyChanged("Count"); 
      OnPropertyChanged("Item[]"); 
     } 
    } 

    public override UIElement this[int index] 
    { 
     get 
     { 
      return base[index]; 
     } 
     set 
     { 
      base[index] = value; 
      var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, index); 
      OnCollectionChanged(args); 
      OnPropertyChanged("Item[]"); 
     } 
    } 

    public event NotifyCollectionChangedEventHandler CollectionChanged; 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     var handler = CollectionChanged; 
     if (handler != null) 
      handler(this, e); 
    } 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

MyUniformGrid

public class MyUniformGrid : UniformGrid 
{ 
    protected override UIElementCollection CreateUIElementCollection(FrameworkElement logicalParent) 
    { 
     return new ObservableUIElementCollection(this, logicalParent); 
    } 
} 

XAML

<local:MyUniformGrid x:Name="MyUniformGrid" 
    Rows="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=R}" 
    Columns="{Binding RelativeSource={RelativeSource Self}, Path=Children.Count, Converter={StaticResource CountToDimensionConverter}, ConverterParameter=C}"> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
    <Button Content="Hello, World!" /> 
</local:MyUniformGrid>