为什么这个附件 属性 没有更新?
Why is this attached property not updating?
好吧,所以我原本只是想 post 解决为什么绑定不起作用的问题。但是,一旦我尝试将代码最小化到 post 上,它又产生了另一个问题。
因此,从本质上讲,Extensions
class 旨在挂钩 ListBox
并制作 SelectedItems
的可绑定版本。这个抓取 SelectedItems
并将它们放在 Selected
附加 属性 中的功能在我的程序中有效(在我的真实程序中它似乎没有绑定?),但在这个最小化版本中不起作用.然而,我不知道为什么,代码似乎完成了它需要做的所有事情。
我用来测试的代码:
.xaml.cs
namespace MyNamespace
{
public partial class MainWindow
{
public IList Selected { get; set; }
public MainWindow()
{
InitializeComponent();
Selected = new List<object>();
Why.ItemsSource = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}
private void Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Selected.Cast<object>().Aggregate("", (s, info) => $"{s}{info}, ").TrimEnd(',', ' '));
MessageBox.Show(Extensions.GetSelected(Why).Cast<object>().Aggregate("", (s, o) => $"{s}{o}, ").TrimEnd(',', ' '));
}
}
public static class Extensions
{
public static readonly DependencyProperty SelectedProperty = DependencyProperty.RegisterAttached(
"Selected", typeof(IList), typeof(Extensions), new PropertyMetadata(default(IList), HookSelectionChanged));
private static void HookSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ListBox lb = sender as ListBox;
if (lb == null)
throw new ArgumentException("This property currently only supports DependencyObjects inheriting from Selector.", nameof(sender));
lb.SelectionChanged += SelectionChanged;
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
=> SetSelected((ListBox)sender, ((ListBox)sender).SelectedItems.Cast<object>().ToList());
public static void SetSelected(DependencyObject element, IList value) => element.SetValue(SelectedProperty, value);
public static IList GetSelected(DependencyObject element) => (IList)element.GetValue(SelectedProperty);
}
}
.xaml
<Window x:Class="MyNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcl="clr-namespace:MyNamespace"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="My title." Height="350" Width="425" MaxHeight="350" MaxWidth="425" MinHeight="350" MinWidth="425">
<StackPanel>
<ListBox lcl:Extensions.Selected="{Binding Selected}" x:Name="Why" SelectionMode="Extended"/>
<Button Click="Click" Content="blah"/>
</StackPanel>
</Window>
任何想法都会很棒!谢谢:)
好吧,我只是错过了两件事:
- 我没有在测试中实现
INotifyPropertyChanged
- 我不知道
Binding
s 并非一直默认为 TwoWay
。
所以所有需要做的是:
.xaml.cs
namespace MyNamespace
{
public partial class MainWindow : INotifyPropertyChanged
{
private IList _selected;
public IList Selected
{
get { return _selected; }
set
{
if (Equals(value, _selected)) return;
_selected = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
Selected = new List<object>();
Why.ItemsSource = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}
private void Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Selected.Cast<object>().Aggregate("", (s, info) => $"{s}{info}, ").TrimEnd(',', ' '));
MessageBox.Show(Extensions.GetSelected(Why).Cast<object>().Aggregate("", (s, o) => $"{s}{o}, ").TrimEnd(',', ' '));
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Extensions
{
public static readonly DependencyProperty SelectedProperty = DependencyProperty.RegisterAttached(
"Selected", typeof(IList), typeof(Extensions), new FrameworkPropertyMetadata(default(IList), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, HookSelectionChanged));
private static void HookSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ListBox lb = sender as ListBox;
if (lb == null)
throw new ArgumentException("This property currently only supports DependencyObjects inheriting from Selector.", nameof(sender));
lb.SelectionChanged += SelectionChanged;
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
=> SetSelected((ListBox)sender, ((ListBox)sender).SelectedItems.Cast<object>().ToList());
public static void SetSelected(DependencyObject element, IList value) => element.SetValue(SelectedProperty, value);
public static IList GetSelected(DependencyObject element) => (IList)element.GetValue(SelectedProperty);
}
}
而且效果非常好。
好吧,所以我原本只是想 post 解决为什么绑定不起作用的问题。但是,一旦我尝试将代码最小化到 post 上,它又产生了另一个问题。
因此,从本质上讲,Extensions
class 旨在挂钩 ListBox
并制作 SelectedItems
的可绑定版本。这个抓取 SelectedItems
并将它们放在 Selected
附加 属性 中的功能在我的程序中有效(在我的真实程序中它似乎没有绑定?),但在这个最小化版本中不起作用.然而,我不知道为什么,代码似乎完成了它需要做的所有事情。
我用来测试的代码:
.xaml.cs
namespace MyNamespace
{
public partial class MainWindow
{
public IList Selected { get; set; }
public MainWindow()
{
InitializeComponent();
Selected = new List<object>();
Why.ItemsSource = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}
private void Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Selected.Cast<object>().Aggregate("", (s, info) => $"{s}{info}, ").TrimEnd(',', ' '));
MessageBox.Show(Extensions.GetSelected(Why).Cast<object>().Aggregate("", (s, o) => $"{s}{o}, ").TrimEnd(',', ' '));
}
}
public static class Extensions
{
public static readonly DependencyProperty SelectedProperty = DependencyProperty.RegisterAttached(
"Selected", typeof(IList), typeof(Extensions), new PropertyMetadata(default(IList), HookSelectionChanged));
private static void HookSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ListBox lb = sender as ListBox;
if (lb == null)
throw new ArgumentException("This property currently only supports DependencyObjects inheriting from Selector.", nameof(sender));
lb.SelectionChanged += SelectionChanged;
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
=> SetSelected((ListBox)sender, ((ListBox)sender).SelectedItems.Cast<object>().ToList());
public static void SetSelected(DependencyObject element, IList value) => element.SetValue(SelectedProperty, value);
public static IList GetSelected(DependencyObject element) => (IList)element.GetValue(SelectedProperty);
}
}
.xaml
<Window x:Class="MyNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcl="clr-namespace:MyNamespace"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="My title." Height="350" Width="425" MaxHeight="350" MaxWidth="425" MinHeight="350" MinWidth="425">
<StackPanel>
<ListBox lcl:Extensions.Selected="{Binding Selected}" x:Name="Why" SelectionMode="Extended"/>
<Button Click="Click" Content="blah"/>
</StackPanel>
</Window>
任何想法都会很棒!谢谢:)
好吧,我只是错过了两件事:
- 我没有在测试中实现
INotifyPropertyChanged
- 我不知道
Binding
s 并非一直默认为TwoWay
。
所以所有需要做的是:
.xaml.cs
namespace MyNamespace
{
public partial class MainWindow : INotifyPropertyChanged
{
private IList _selected;
public IList Selected
{
get { return _selected; }
set
{
if (Equals(value, _selected)) return;
_selected = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
Selected = new List<object>();
Why.ItemsSource = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}
private void Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Selected.Cast<object>().Aggregate("", (s, info) => $"{s}{info}, ").TrimEnd(',', ' '));
MessageBox.Show(Extensions.GetSelected(Why).Cast<object>().Aggregate("", (s, o) => $"{s}{o}, ").TrimEnd(',', ' '));
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Extensions
{
public static readonly DependencyProperty SelectedProperty = DependencyProperty.RegisterAttached(
"Selected", typeof(IList), typeof(Extensions), new FrameworkPropertyMetadata(default(IList), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, HookSelectionChanged));
private static void HookSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ListBox lb = sender as ListBox;
if (lb == null)
throw new ArgumentException("This property currently only supports DependencyObjects inheriting from Selector.", nameof(sender));
lb.SelectionChanged += SelectionChanged;
}
private static void SelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
=> SetSelected((ListBox)sender, ((ListBox)sender).SelectedItems.Cast<object>().ToList());
public static void SetSelected(DependencyObject element, IList value) => element.SetValue(SelectedProperty, value);
public static IList GetSelected(DependencyObject element) => (IList)element.GetValue(SelectedProperty);
}
}
而且效果非常好。