我想创建一个附加属性,以便在我的视图模型中访问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然后它永远不会将新对话框订阅到该事件
无论如何,在这种情况下,我有同样的疑问,当我关闭对话框时,我不会看到该事件何时取消订阅。
感谢。
答案 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!");
}
}