何时何地取消订阅对话中的附加财产?

时间:2017-08-26 11:02:13

标签: c# wpf attached-properties

我想创建一个附加属性,以便在我的视图模型中访问listBox的SelectedItems。

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

我怀疑的是,当事件不需要时,没有取消订阅。

在我的情况下,我将在对话框中使用附加属性,因此我将创建我的视图,我的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为true然后它永远不会将新对话框订阅到该事件

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

感谢。

1 个答案:

答案 0 :(得分: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!");
     }

}