2016-04-12 9 views
-1

申し訳ありませんが、もともとは、バインディングが機能していなかった理由の問題として投稿するつもりでした。しかし、私がSOに投稿するコードを最小限にしようとするとすぐに、それはさらに別の問題を作り出しました。この添付プロパティが更新されないのはなぜですか?

したがって、Extensionsクラスは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> 

任意のアイデアは素晴らしいだろう!感謝:)

+1

これは役に立つかもしれません:https://spin.atomicobject.com/2013/12/11/wpf-data-binding-debug/そのPresentationTraceSources.TraceLevelは私にとって毎日の命を救う人です(whoops、あなたのDataContextバインディング) –

+1

'{Binding Selected、' = TwoWay} 'は' {Binding Selected} 'ではありませんか? – Quantic

+0

@Quanticが正しいです - あなたは 'PropertyMetadata'の代わりに[' FrameworkPropertyMetadata'](https://msdn.microsoft.com/en-us/library/ms557295(v = vs.110).aspx)を使うこともできます。 'FrameworkPropertyMetadataOptions.BindsTwoWayByDefault'を渡すことができるので、消費者は' Mode = TwoWay'を追加するのを忘れる必要はありません。 –

答えて

0

さて、それがすべてだったが、私が行方不明になった二つのこと:

  • 私は私のテストで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); 
    } 
} 

、それは見事に働きました。

関連する問題