I'm trying to implement the example at:
https://github.com/olohmann/WpfRxControls
There are three parts to the custom control:
PART_TextBox
PART_Popup
PART_ListBox
Relevant source:
https://github.com/olohmann/WpfRxControls/blob/master/WpfRxControls/AutoCompleteTextBox.cs
https://github.com/olohmann/WpfRxControls/blob/master/WpfRxControls/Themes/Generic.xaml
All the pieces are in place, and the code using the new control is as follows:
<ctrls:AutoCompleteTextBox
Grid.Row="1"
AutoCompleteQueryResultProvider="{Binding AutoCompleteQueryResultProvider}"
Margin="10" FontSize="20" PopupHeight="300">
</ctrls:AutoCompleteTextBox>
I just need to hook into the ListBox's SelectionChanged event in my pages XAML / ViewModel, how can this be accomplished?
Edit: In XAML / VM, not view code behind. Thus far all view code behinds are empty and I'd like to keep it that way.
I thought there was some way to override PART_ListBox in a ControlTemplate override in MainWindow.XAML?
Edit: Final solution, thanks to mm8
In the AutoCompleteTextBox.cs, create a dependency property of type 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));
In the SetResultText method:
AutoCompleteSelectionChangedCommand?.Execute(autoCompleteQueryResult);
View / ViewModel usage:
<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
}
You could handle the Loaded event of the AutoCompleteTextBox in the view, get a reference to the PART_ListBox in the control template using the FindName method and then hook up an event handler for the SelectionChanged event of the ListBox:
Your view model class has no (and shouldn't have any) reference nor knowledge about the ListBox that is part of the template of the control.
Then you will have to override/re-define the entire ControlTemplate of the AutoCompleteTextBox control which seems a bit unnecessary.
MVVM is not about eliminating code from the views - it's about separation of concerns and whether you hook up an event handler from the XAML markup of the view or the code-behind of the very same view makes no difference at all as far as the design pattern is concerned.
Edit: But if you want to keep the code-behind classes clean you could implement this using an attached behaviour:
Introduction to Attached Behaviors in WPF: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF