2017-08-26 3 views
0

Je veux créer une propriété attachée pour avoir accès à SelectedItems d'un listBox dans mon modèle de vue.Où ou quand vous désinscrire une propriété jointe dans une boîte de dialogue?

L'exemple le plus simple sur une propriété attachée est ce (pour une zone de texte, non listBox, mais pour un premier apprentissage, je pense qu'il suffit):

public static bool GetAllowOnlyString(DependencyObject obj) 
{ 
    return (bool)obj.GetValue(AllowOnlyStringProperty); 
} 
public static void SetAllowOnlyString(DependencyObject obj, bool value) 
{ 
    obj.SetValue(AllowOnlyStringProperty, value); 
} 
// Using a DependencyProperty as the backing store for AllowOnlyString. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty AllowOnlyStringProperty = 
DependencyProperty.RegisterAttached("AllowOnlyString", typeof(bool),typeof(TextblockExtension), new PropertyMetadata(false, AllowOnlyString)); 
private static void AllowOnlyString(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    if (d is TextBox) 
    { 
     TextBox txtObj = (TextBox)d; 
     txtObj.TextChanged += (s, arg) => 
     { 
     TextBox txt = s as TextBox; 
     if (!Regex.IsMatch(txt.Text, "^[a-zA-Z]*$")) 
     { 
      txtObj.BorderBrush = Brushes.Red; 
      MessageBox.Show("Only letter allowed!"); 
     } 
     }; 
    } 
} 

je peux voir que si l'objet est TextBox, alors il est souscrit à l'événement TextChanged à la méthode qui traite le texte.

Mon doute est qu'il n'y a pas de désinscription à l'événement quand il n'est pas nécessaire.

Dans mon cas, je vais utiliser la propriété jointe dans une boîte de dialogue, donc je vais créer ma vue, mon viewModel et j'utiliserai la propriété attachée pour qu'elle s'abonne à l'événement, mais quand je fermerai la boîte de dialogue , l'événement n'est pas désinscrit. Vraiment je verrais un autre exemple avec un comportement attaché, mais pour moi c'est un peu plus complexe, et vraiment je ne connais pas la différence entre les propriétés attachées et le comportement attaché, donc dans ce cas je voudrais apprendre utiliser la propriété jointe.

Un autre exemple est la suivante:

public class ListBoxSelectedItemsAttachedProperty 
    { 
     #region SelectedItems 
     private static ListBox list; 
     private static bool _isRegisteredSelectionChanged = false; 

     /// 
     /// SelectedItems Attached Dependency Property 
     /// 
     public static readonly DependencyProperty SelectedItemsProperty = 
     DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), 
     typeof(ListBoxSelectedItemsAttachedProperty), 
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault 
      ,new PropertyChangedCallback(OnSelectedItemsChanged) 
      )); 

     public static IList GetSelectedItems(DependencyObject d) 
     { 
      return (IList)d.GetValue(SelectedItemsProperty); 
     } 

     public static void SetSelectedItems(DependencyObject d, IList value) 
     { 
      d.SetValue(SelectedItemsProperty, value); 
     } 

     private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      if (!_isRegisteredSelectionChanged) 
      { 
       ListBox listBox = (ListBox)d; 
       list = listBox; 
       listBox.SelectionChanged += listBox_SelectionChanged; 
       _isRegisteredSelectionChanged = true; 
      } 
     } 

     private static void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      //Get list box's selected items. 
      IEnumerable listBoxSelectedItems = list.SelectedItems; 
      //Get list from model 
      IList ModelSelectedItems = GetSelectedItems(list); 

      //Update the model 
      ModelSelectedItems.Clear(); 

      if (list.SelectedItems != null) 
      { 
       foreach (var item in list.SelectedItems) 
        ModelSelectedItems.Add(item); 
      } 
      SetSelectedItems(list, ModelSelectedItems); 
     } 
     #endregion 
    } 

Il fonctionne quand j'ouvre la première fois dialogue, mais si je ferme et la boîte de dialogue et ouvert à nouveau, il ne fonctionne pas parce que la propriété statique isRegisteredSelectionChanged est vrai et alors il ne souscrira jamais le nouveau dialogue à l'événement.

De toute façon dans ce cas, j'ai le même doute, que je ne vois pas quand l'événement sera désinscrit lorsque je ferme la boîte de dialogue.

Merci.

Répondre

1

Si votre boîte de dialogue est retirée après la clôture, vous pouvez essayer un petit hack:

private static void AllowOnlyString(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 

    if (d is TextBox) 
    { 
     TextBox txtObj = (TextBox)d; 
     txtObj.TextChanged += Validation; 
     txtObj.Unloaded += Unload; 

    } 
} 

private static void Unload(object sender, RoutedEventArgs e) 
{ 
    var x = (TextBox)sender; 
    x.Unloaded -= Unload; 
    x.TextChanged -= Validation; 
} 

private static void Validation(object sender, TextChangedEventArgs e) 
{  
    TextBox txtObj = sender as TextBox; 
    if (!Regex.IsMatch(txtObj.Text, "^[a-zA-Z]*$")) 
    { 
     txtObj.BorderBrush = Brushes.Red; 
     MessageBox.Show("Only letter allowed!"); 
    } 

} 
+0

Merci, cela fonctionne très bien et il est une solution simple. –