2017-01-22 19 views
2

Я пытаюсь реализовать пример по адресу:Привязать к событию в рамках таможенного контроля

https://github.com/olohmann/WpfRxControls

Есть три части таможенного контроля:

PART_TextBox

PART_Popup

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 не просматривать код позади. До сих пор все образы кода выглядят пустыми, и я хотел бы сохранить их таким образом.

Я думал, что есть какой-то способ переопределить PART_ListBox в переопределении ControlTemplate в MainWindow.XAML?

Edit: Окончательное решение, благодаря MM8

В разделе AutoCompleteTextBox.cs, создать свойство зависимостей типа ICommand:

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)); 

В методе SetResultText:

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

Вы можете обрабатывать Loaded событие AutoCompleteTextBox в представлении, получить ссылку на PART_ListBox в шаблоне управления с использованием метода FindName, а затем подключить обработчик для события SelectionChanged в ListBox:

<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; 
     }; 
    } 
} 

Ваше мнение модель класс не имеет (и не должен иметь) ссылки, ни знание о ListBox, который является частью шаблона элемента управления.

Я думал, что есть какой-то способ переопределить PART_ListBox в переопределении ControlTemplate в MainWindow.XAML?

Тогда вам придется переопределить/повторно определить весь ControlTemplate элемента управления AutoCompleteTextBox который кажется немного ненужным.

MVVM является не об устранении кода с мнения - это о разделении проблем и является ли вы подключить обработчик событий из XAML разметки представления или отделенный код из того же точки зрения нет никакой разницы в все, что касается шаблона проектирования.

Edit: Но если вы хотите сохранить отделенный код классов чистыми вы могли бы реализовать это с помощью прикрепленного поведения:

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> 

Введения Attached поведений в WPF:https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF

+0

До сих пор я остался подальше от написания кода в виде кода позади, m Конечно, есть способ подключиться к этому в XAML, но я не уверен, что синтаксис должен переопределить некоторые из PART_ListBox. – Jack

+0

Вы не можете переопределить * некоторые * из PART_ListBox или какую-либо часть шаблона управления AutoCompleteTextBox контроль. Затем вам придется переопределить весь шаблон управления. – mm8

+0

Или можно переместить код с кодового обозначения представления в прикрепленное поведение. См. Мой отредактированный ответ. – mm8