2017-01-22 1 views
2

は時:バインド

PART_TextBox

PART_Popup:

https://github.com/olohmann/WpfRxControls

カスタムコントロールの3つの部分があります。

PART_ListBox

関連するソース:

https://github.com/olohmann/WpfRxControls/blob/master/WpfRxControls/AutoCompleteTextBox.cs

https://github.com/olohmann/WpfRxControls/blob/master/WpfRxControls/Themes/Generic.xaml

すべてのピースが所定の位置にあり、かつ、次のように新しいコントロールを使用するコードは次のとおりです。

<ctrls:AutoCompleteTextBox 
      Grid.Row="1" 
      AutoCompleteQueryResultProvider="{Binding AutoCompleteQueryResultProvider}" 
      Margin="10" FontSize="20" PopupHeight="300"> 

</ctrls:AutoCompleteTextBox> 

は、私はちょうどにフックする必要があります私のページのListBoxのSelectionChangedイベントXAML/ViewModel、これはどのように達成できますか?

編集:XAML/VMでは、コードを表示しません。これまでのところ、すべてのビューコードの背後は空であり、私はそれをそのままにしておきたいと思います。

MainWindow.XAMLのControlTemplateオーバーライドでPART_ListBoxをオーバーライドする方法があると思いましたか?

編集:最終溶液、おかげで、AutoCompleteTextBox.csで

をMM8タイプの依存性を作成するためのICommand:SetResultText方法において

public const string AutoCompleteSelectionChangedPropertyName = "AutoCompleteSelectionChangedCommand"; 

     public ICommand AutoCompleteSelectionChangedCommand 
     { 
      get { return (ICommand) GetValue(AutoCompleteSelectionChangedProperty); } 
      set { SetValue(AutoCompleteSelectionChangedProperty, value);} 
     } 

     public static readonly DependencyProperty AutoCompleteSelectionChangedProperty = DependencyProperty.Register(
      AutoCompleteSelectionChangedPropertyName, 
      typeof(ICommand), 
      typeof(AutoCompleteTextBox)); 

AutoCompleteSelectionChangedCommand?.Execute(autoCompleteQueryResult); 

表示/表示モデル使用:

<ac:AutoCompleteTextBox Name="AutoComplete" 
    AutoCompleteQueryResultProvider="{Binding AutoCompleteQueryResultProvider}" 
    FontSize="12" 
    AutoCompleteSelectionChangedCommand="{Binding CommandEditValueChanged}"> 
</ac:AutoCompleteTextBox> 


public ICommand CommandEditValueChanged { get; set; } 

public MainWindowViewModel(){ 
    CommandEditValueChanged = new DelegateCommand<object>(OnEditValueChanged); 
} 

private void OnEditValueChanged(object result){ 
    // do stuff 
} 

答えて

2

あなたは、ビュー内のAutoCompleteTextBoxのLoadedイベントを処理FindName指定方法を使用してコントロールテンプレートにPART_ListBoxへの参照を取得し、リストボックスのSelectionChangedイベントのイベントハンドラをフックできます

<ctrls:AutoCompleteTextBox 
      Grid.Row="1" 
      AutoCompleteQueryResultProvider="{Binding AutoCompleteQueryResultProvider}" 
      Margin="10" FontSize="20" PopupHeight="300" Loaded="AutoCompleteTextBox_Loaded"> 

</ctrls:AutoCompleteTextBox> 

private void AutoCompleteTextBox_Loaded(object sender, RoutedEventArgs e) 
{ 
    AutoCompleteTextBox actb = sender as AutoCompleteTextBox; 
    ListBox lb = actb.Template.FindName("PART_ListBox", actb) as ListBox; 
    if (lb != null) 
    { 
     lb.SelectionChanged += (ss, ee) => 
     { 
      MainWindowViewModel vm = DataContext as MainWindowViewModel; 
      //invoke a command of the view model or do whatever you want here... 
      var selectedItem = lb.SelectedItem; 
     }; 
    } 
} 

あなたのビューモデルクラスは全くありません(と任意の必要はありません)コントロールのテンプレートの一部であるリストボックスについての言及も知識を。

MainWindow.XAMLのControlTemplateオーバーライドでPART_ListBoxをオーバーライドする方法があると思いましたか?

次に、あなたが上書き/再定義ビット不要と思われるAutoCompleteTextBox制御の全体のControlTemplateを持つことになります。

MVVMがビューからコードを削除することについて - これは懸念の分離に関するものであり、ビューのXAMLマークアップからイベントハンドラを引き出すのか、まったく同じビューのコードビハインドでも違いはありませんすべてデザインパターンに関する限りです。

編集:しかし、あなたはクリーンなコードビハインドクラスを維持したい場合は、この接続動作を使用して実装することができます:WPFでの添付行動に

public class AutoCompleteBoxBehavior 
{ 
    public static ICommand GetSelectionChangedCommand(AutoCompleteTextBox actb) 
    { 
     return (ICommand)actb.GetValue(SelectionChangedCommandProperty); 
    } 

    public static void SetSelectionChangedCommand(AutoCompleteTextBox actb, ICommand value) 
    { 
     actb.SetValue(SelectionChangedCommandProperty, value); 
    } 

    public static readonly DependencyProperty SelectionChangedCommandProperty = 
     DependencyProperty.RegisterAttached(
     "SelectionChangedCommand", 
     typeof(ICommand), 
     typeof(AutoCompleteBoxBehavior), 
     new UIPropertyMetadata(null, OnHandleSelectionChangedEvent)); 

    private static void OnHandleSelectionChangedEvent(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ICommand command = e.NewValue as ICommand; 
     if(command != null) 
     { 
      AutoCompleteTextBox actb = d as AutoCompleteTextBox; 
      actb.Loaded += (ss, ee) => 
      { 
       ListBox lb = actb.Template.FindName("PART_ListBox", actb) as ListBox; 
       if (lb != null) 
       { 
        lb.SelectionChanged += (sss, eee) => 
        { 
         command.Execute(null); 
        }; 
       } 
      }; 
     } 
    } 
} 

<ctrls:AutoCompleteTextBox 
     Grid.Row="1" 
     AutoCompleteQueryResultProvider="{Binding AutoCompleteQueryResultProvider}" 
     Margin="10" FontSize="20" PopupHeight="300" 
     local:AutoCompleteBoxBehavior.SelectionChangedCommand="{Binding YourCommand}"> 
</ctrls:AutoCompleteTextBox> 

はじめに:https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF

+0

これまでのところ、私はビューコードの背後にコードを書かずにいましたが、私はXAMLでこれにフックする方法があると確信していますが、PART_ListBoxの一部をオーバーライドする構文がわかりません – Jack

+0

PART_ListBoxの*いくつかの*またはAutoCompleteTextBoxのコントロールテンプレートの一部をオーバーライドできませんコントロール。コントロールテンプレート全体を再定義する必要があります。 – mm8

+0

または、ビューのコードビハインドからコードを添付のビヘイビアに移動できます。私の編集された答えを見てください。 – mm8