何时何地取消订阅对话框中附加的 属性?
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!");
}
}
我想创建一个附加的 属性 以访问我的视图模型中列表框的 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!");
}
}