何时何地取消订阅对话框中附加的 属性?

Where or when to unsubscribe an attached property in a dialog?

我想创建一个附加的 属性 以访问我的视图模型中列表框的 SelectedItems。

关于附加 属性 的最简单示例是这个(对于文本框,而不是 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 到处理文本的方法。

我怀疑在不需要的时候没有取消订阅该活动。

在我的例子中,我将在对话框中使用附加的 属性,因此我将创建我的视图、我的 viewModel,我将使用附加的 属性 来订阅事件,然而,当我关闭对话框时,事件并没有取消订阅。

我真的会看到另一个带有附加行为的例子,但对我来说它有点复杂,而且我真的不知道附加属性和附加行为之间的区别,所以在这种情况下我想学习使用附件 属性.

另一个例子是这样的:

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 为真,然后它将永远不会订阅新的事件对话。

无论如何在这种情况下我有同样的疑问,当我关闭对话框时我没有看到事件何时取消订阅。

谢谢。

如果您的对话框在关闭后被删除,您可以尝试一些破解:

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

}