Где или когда отписаться от прикрепленного свойства в диалоговом окне?

Я хочу создать прикрепленное свойство, чтобы иметь доступ к SelectedItems спискаBox в моей модели представления.

Самый простой пример с прикрепленным свойством (для textBox, а не для lIstBox, но для первого изучения думаю достаточно):

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

Я вижу, что если объект это TextBox, то он подписывается на событие TextChanged для метода, обрабатывающего текст.

Сомневаюсь, что нет отписки на событие, когда оно не нужно.

В моем случае я буду использовать прикрепленное свойство в диалоговом окне, поэтому я создам свое представление, свою модель представления, и я буду использовать прикрепленное свойство, которое подпишется на событие, однако, когда я закрою диалоговое окно, событие не отписываться.

На самом деле я бы увидел еще один пример с прикрепленным поведением, но для меня это немного сложнее, и я действительно не знаю разницы между прикрепленными свойствами и присоединенным поведением, поэтому в этом случае я хотел бы научиться использовать прикрепленное имущество.

Другой пример:

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
    }

Это работает, когда я открываю диалоговое окно в первый раз, но если я закрою диалоговое окно и открою его снова, это не сработает, потому что статическое свойство isRegisteredSelectionChanged равно true, и тогда он никогда не подпишет новый диалог на событие.

Во всяком случае, в этом случае у меня есть такое же сомнение, что я не вижу, когда событие будет отписано, когда я закрываю диалог.

Спасибо.


person Álvaro García    schedule 26.08.2017    source источник


Ответы (1)


Если ваш диалог удаляется после закрытия, вы можете попробовать небольшой хак:

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

}
person sTrenat    schedule 26.08.2017