I am trying to change the source property of the frame in Page1.xaml when the SampleCommand is excecuted.
How do I acheive this in the View Model?
Page1.xaml:
<r:RibbonTab.Groups>
<r:RibbonGroup GroupSizeDefinitions="{StaticResource RibbonLayout}">
<r:RibbonGroup.Command>
<r:RibbonCommand LabelTitle="RibbonButton"/>
</r:RibbonGroup.Command>
<r:RibbonButton x:Name="RibbonButton1" Command="{Binding Path=SampleCommand}"/>
</r:RibbonGroup>
</r:RibbonTab.Groups>
</r:RibbonTab>
</r:Ribbon>
<Border Name="PageBorder" Grid.Row="0" Grid.Column="1">
<Frame Name="pageFrame" Source="FirstPage.xaml" />
</Border>
</DockPanel>
c#
Page1ViewModel.cs:
RelayCommand _sampleCommand;
public ICommand SampleCommand
{
get
{
// create command ??
return _sampleCommand
}
page1.xaml.cs :
Page1ViewModel pageViewModel;
this.DataContext = pageViewModel; // when pageloads
Have you tried to use is this way?
public class ViewModel{
private SimpleCommand divertCommand;
public ViewModel()
{
testCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = x => ExecuteCommand()
};
}
public SimpleCommand DivertCommand
{
get { return divertCommand; }
}
private void ExecuteCommand()
{
DivertCommand.CommandSucceeded = false;
//Your code to execute
DivertCommand.CommandSucceeded = true;
}}
}
please use this project as a reference: link
there is a nice thread here
Good luck
Ric
Related
I'm creating a WPF Molds app that contains 2 windows: MainWindow with DataGrid, and AddEditWindow which allows to Add/Edit Molds.
I have a EditButton which located in a TemplateColumn of DataGrid:
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Width="150"
Height="40"
BorderThickness="2"
BorderBrush="DarkRed"
Background="Red"
Foreground="White"
Content="Edit"
Name="BtnEdit"
CommandParameter="{Binding}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AddEditWindowCommand}">
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
AddEditWindowCommand:
public ICommand AddEditWindowCommand { get; }
private bool CanAddEditWindowCommandExecute(object SelectedRow) => true;
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow();
window.Show();
}
And I want to pass DataContext to the AddEditWindowViewModel. In a Code-Behind, I could done something like this:
private void BtnEdit_Click(object sender, RoutedEventArgs e)
{
AddEditWindow addEditWindow = new AddEditWindow((sender as Button).DataContext as Molds);
addEditWindow.Show();
}
And then retrieve it AddEditWindow like this:
private Molds _currentMold = new Molds();
public GamesEdit(Molds selectedMold)
{
InitializeComponent();
if (selectedMold != null)
{
_currentMold = selectedMold;
}
DataContext = _currentMold;
But in MVVM I can't. So, is there a way to do it without breaking MVVM pattern?
p.s. since I'm new to the MVVM, I would really appreciate detailed explanation.
update:
MainWindowViewModel:
internal class MainWindowViewModel : ViewModel
{
#region Variables
#region Textblocks for search
private Molds newMolds { get; set; } = new Molds();
public string TxtType
{
get => newMolds.Type;
set => newMolds.Type = value;
}
public string TxtName
{
get => newMolds.Name;
set => newMolds.Name = value;
}
public string TxtKus
{
get => newMolds.Kus;
set => newMolds.Kus = value;
}
#endregion
#region AllMolds
private ObservableCollection<Molds> allMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
public ObservableCollection<Molds> AllMolds
{
get => allMolds;
set => allMolds = value;
}
#endregion
#region FilteredMolds
private ObservableCollection<Molds> filteredMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
public ObservableCollection<Molds> FilteredMolds
{
get
{
filteredMolds = AllMolds;
var currentfilteredmolds = new List<Molds>(filteredMolds);
if (TxtName != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Name.ToLower().Contains(TxtName.ToLower())).ToList();
if (TxtType != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Type.ToLower().Contains(TxtType.ToLower())).ToList();
if (TxtKus != null)
currentfilteredmolds = currentfilteredmolds.Where(p => p.Kus.ToLower().Contains(TxtKus.ToLower())).ToList();
return new ObservableCollection<Molds>(currentfilteredmolds);
}
set => filteredMolds = value;
}
#endregion
#endregion
#region Commands
#region CloseApplicationCommand
public ICommand CloseApplicationCommand { get; }
private bool CanCloseApplicationCommandExecute(object p) => true;
private void OnCloseApplicationCommandExecuted(object p)
{
Application.Current.Shutdown();
}
#endregion
#region SearchCommand
public ICommand SearchCommand { get; }
private bool CanSearchCommandExecute(object p) => true;
private void OnSearchCommandExecuted(object p)
{
OnPropertyChanged("FilteredMolds");
}
#endregion
#region Open AddEditWindowCommand
public ICommand AddEditWindowCommand { get; }
private bool CanAddEditWindowCommandExecute(object SelectedRow) => true;
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow();
window.Show();
}
#endregion
#region DeleteMoldCommand
public ICommand DeleteMoldCommand { get; }
private bool CanDeleteMoldCommandExecute(object SelectedItems)
{
if (SelectedItems != null) return true; else return false;
}
private void OnDeleteMoldCommandExecuted(object SelectedItems)
{
System.Collections.IList items = (System.Collections.IList)SelectedItems;
var moldsforRemoving = items?.Cast<Molds>().ToList();
if (MessageBox.Show($"You want to remove the following {moldsforRemoving.Count()} molds?", "Attention",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
try
{
ApplicationContext.GetContext().Molds.RemoveRange(moldsforRemoving);
ApplicationContext.GetContext().SaveChanges();
MessageBox.Show("Data deleted successfully.", "Data deletion",
MessageBoxButton.OK, MessageBoxImage.Information);
AllMolds = new ObservableCollection<Molds>(ApplicationContext.GetContext().Molds.ToList());
OnPropertyChanged("FilteredMolds");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString(), "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
#endregion
#region DragMoveCommand
public ICommand DragMoveCommand { get; }
private bool CanDragMoveCommandExecute(object p) => true;
private void OnDragMoveCommandExecuted(object p)
{
Application.Current.MainWindow.DragMove();
}
#endregion
#endregion
public MainWindowViewModel()
{
#region Command Samples
CloseApplicationCommand = new LamdaCommand(OnCloseApplicationCommandExecuted, CanCloseApplicationCommandExecute);
SearchCommand = new LamdaCommand(OnSearchCommandExecuted, CanSearchCommandExecute);
AddEditWindowCommand = new LamdaCommand(OnAddEditWindowCommandExecuted, CanAddEditWindowCommandExecute);
DeleteMoldCommand = new LamdaCommand(OnDeleteMoldCommandExecuted, CanDeleteMoldCommandExecute);
DragMoveCommand = new LamdaCommand(OnDragMoveCommandExecuted, CanDragMoveCommandExecute);
#endregion
#region Variable Samples for searching
TxtName = null;
TxtKus = null;
TxtType = null;
#endregion
}
}
AddEditWindowViewModel
internal class AddEditWindowViewModel : ViewModel
{
#region Variables
private Molds _currentMold = new Molds();
#endregion
#region Commands
#region CloseWindowCommand
public ICommand CloseWindowCommand { get; }
private bool CanCloseWindowCommandExecute(object p) => true;
private void OnCloseWindowCommandExecuted(object p)
{
Application.Current.Windows[1].Close();
}
#endregion
#region DragMoveAddEditWindowCommand
public ICommand DragMoveAddEditWindowCommand { get; }
private bool CanDragMoveAddEditWindowCommandExecute(object p) => true;
private void OnDragMoveAddEditWindowCommandExecuted(object p)
{
Application.Current.Windows[1].DragMove();
}
#endregion
#endregion
public AddEditWindowViewModel()
{
#region Command samples
CloseWindowCommand = new LamdaCommand(OnCloseWindowCommandExecuted, CanCloseWindowCommandExecute);
DragMoveAddEditWindowCommand = new LamdaCommand(OnDragMoveAddEditWindowCommandExecuted, CanDragMoveAddEditWindowCommandExecute);
#endregion
}
}
I connect them to the window using <Window.DataContext>:
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
Same goes for the AddEditWindowViewModel.
DataGrid binding:
<DataGrid x:Name="DGridMolds"
AutoGenerateColumns="False"
IsReadOnly="True"
Foreground="White"
BorderBrush="White"
Background="#2b2a38"
Grid.Column="1"
Grid.Row="1"
ItemsSource="{Binding Path=FilteredMolds}"
>
AddEditWindow.Xaml:
<Window.DataContext>
<vm:AddEditWindowViewModel/>
</Window.DataContext>
<Border Background="#2f2e3c"
CornerRadius="10">
<Border.InputBindings>
<MouseBinding Command="{Binding DragMoveAddEditWindowCommand}" MouseAction="LeftClick"/>
</Border.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Vertical">
<TextBlock Text="Add" FontSize="22" Foreground="White" HorizontalAlignment="Center" Margin="0,30,0,0"/>
<TextBox Foreground="White" Text="{Binding Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5, 35, 5, 5" materialDesign:HintAssist.Hint="Type"/>
<TextBox Foreground="White" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" materialDesign:HintAssist.Hint="Name"/>
<TextBox Foreground="White" Text="{Binding Kus, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" materialDesign:HintAssist.Hint="Kus"/>
In a Code-Behind, I could done something like this:
Take a closer look at your XAML.
You have a binding set in the CommanParameter property.
The binding instance is empty - this means that the binding occurs to the DataContext of the element in which it is specified.
Hence, in the command parameter, you will get this Data Context.
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow()
{DataContext = SelectedRow};
window.Show();
}
So, is there a way to do it without breaking MVVM pattern?
You've already broken MVVM.
ViewModel is not allowed to work with UI elements.
The ViewModel doesn't even need to know what type of View is using it: WPF, Forms, or Console.
And you CREATE the Window!
This is unacceptable for the MVVM concept.
Addition in connection with showing more detailed code in the main question:
I can't understand the logic of your code.
Therefore, I will write in the measure as I understand your intentions.
AddEditWindowViewModel class - designed for logic for editing and/or adding an item.
But then he has to get this element and provide it in his property so that he can create a GUI for editing.
It should be something like this:
namespace MoldsApp
{
public class AddEditWindowViewModel : ViewModel
{
public Molds CurrentMold { get; }
// Constructor called to edit an entity
public AddEditWindowViewModel(Molds currentMold)
{
CurrentMold = currentMold;
}
//Constructor called to create and edit an entity
public AddEditWindowViewModel()
: this(new Molds())
{
}
}
}
Also, your DataContext is set incorrectly.
By creating it inside XAML, you cannot set the data for this instance of the ViewModel.
Therefore, in XAML, you can instantiate a ViewModel used only at the time of its designed.
For a design-time DataContext, use the d: prefix.
<d:Window.DataContext>
<vm:MainWindowViewModel/>
</d:Window.DataContext>
With these changes, the item edit command should be like this:
private void OnAddEditWindowCommandExecuted(object SelectedRow)
{
AddEditWindow window = new AddEditWindow()
{
DataContext = new AddEditWindowViewModel((Molds)SelectedRow)
};
window.Show();
}
I write new WPF MVVM app.
I new in WPF.
I have problem with binding value to StageControl from MainPageModelView.
StageControl is in MainPage.
I know how binding value to element in MainPage, but I can't binding value to StageControl in this same way.
How can I binding value from MainPageModelView to StageControl?
Code:
MainPage.xaml
<my:StageControl x:Name="stageControl1" StageIsActive="true" StageName="{Binding Stage.Name}" Grid.Row="0" Grid.Column="0"/>
...
<Label x:Name="lbTest" Content="{Binding Test}" HorizontalAlignment="Left" Margin="104,10,0,0" VerticalAlignment="Top" Height="56" Width="68"/>
StageControl.xaml.cs
public partial class StageControl : UserControl
{
string stageName;
bool stageIsActive;
public StageControl()
{
InitializeComponent();
}
public bool StageIsActive
{
get { return this.stageIsActive; }
set { this.stageIsActive = SetStageControlStatus(value); }
}
public string StageName
{
get { return this.stageName; }
set { this.stageName = SetStageName(value); }
}
private bool SetStageControlStatus(bool value)
{
if (value)
{
this.outRing.Visibility = Visibility.Visible;
return true;
}
else
{
this.outRing.Visibility = Visibility.Hidden;
return false;
}
}
private string SetStageName(string value)
{
this.text.Text = value;
return this.text.Text;
}
}
MainPageViewModel.cs
class MainPageViewModel
{
public List<Stage> Stages = new List<Stage>();
public Stage stage = new Stage(0, "Test", true);
public MainPageViewModel()
{
Stages = Stage.GetStages();
}
public string Test
{
get { return "Testowy Label"; }
set { }
}
}
Edit:
MainPage.xaml.css
public MainPage()
{
InitializeComponent();
MainPageViewModel viewModel = new MainPageViewModel();
this.DataContext = viewModel;
}
I solved the problem.
First I add dependency property to StageControl.xaml.cs, then I add binding to StageControl.xaml
...
x:Name="Stage"
...
<TextBlock x:Name="text" TextWrapping="Wrap" Text="{Binding ElementName=Stage, Path=StageName}" TextAlignment="Center" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center"/>
public Stage Stage {get;set;} = new Stage(0,"Test",true);
u need to make property instead of public variable
I want to remove an item from an ObservableCollection while adhering to MVVM. I understand the task, I think I understand the logic pretty well and have implemented it, but the item is never removed in the view.
I have traced the application with breakpoints and the value of selectedProject is being read correctly. I also added variables to check the Collection size before and after the remove statement, which were the same value so it therefore does not remove the item. My question is why? What have I missed? What rules have I not adhered to? Pretty new to .NET.
**I am using a WCF Service, to return an ObservableCollection of Projects from my CodeFirst DB and this is called as soon as a user opens the Projects view.
View
<ListBox ItemsSource="{Binding ProjectList, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedProject}" SelectedIndex="{Binding ProjectIndex}" BorderThickness="0" Margin="60,195,218.8,212.4">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProjectName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Command="{Binding DeleteCommand}" Content="Up" HorizontalAlignment="Left" Margin="563,195,0,0" VerticalAlignment="Top" Height="35" Width="75"/>
ViewModel
private ObservableCollection<Project> _projectList;
public ObservableCollection<Project> ProjectList
{
get
{
var q = client.ReturnProjects().ToList();
_projectList = new ObservableCollection<Project>(q.ToList());
return _projectList;
}
set
{
_projectList = value;
OnPropertyChanged("ProjectList");
}
public int SelectedProject
{
get { return _selectedProject; }
set
{
_selectedProject = value;
OnPropertyChanged("SelectedProject");
}
}
The method executed by the command is as follows, the command is being hit and the method called.
public void DeleteProject()
{
if (SelectedProject != null)
{
ProjectList.Remove(SelectedProject);
}
}
You need a two-way-binding for the SelectedItem property.
View
<ListBox ItemsSource="{Binding ProjectList}"
SelectedItem="{Binding SelectedProject, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Command="{Binding DeleteCommand}"
Content="Delete"
HorizontalAlignment="Right"
VerticalAlignment="Bottom" />
ViewModel, Model and ICommand Implementation
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
var q = new[] { new Project() { Name = "A" }, new Project() { Name = "B" }, new Project() { Name = "C" } };
ProjectList = new ObservableCollection<Project>(q);
}
private ObservableCollection<Project> _projectList;
public ObservableCollection<Project> ProjectList
{
get
{
return _projectList;
}
set
{
_projectList = value;
OnPropertyChanged("ProjectList");
}
}
Project _selectedProject;
public Project SelectedProject
{
get { return _selectedProject; }
set
{
_selectedProject = value;
OnPropertyChanged("SelectedProject");
}
}
public ICommand DeleteCommand => new SimpleCommand(DeleteProject);
private void DeleteProject()
{
if (SelectedProject != null)
{
ProjectList.Remove(SelectedProject);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Project
{
public string Name { get; set; }
}
public class SimpleCommand : ICommand
{
Action _execute;
public SimpleCommand(Action execute)
{
this._execute = execute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
_execute();
}
}
I think OnPropertyChanged("ProjectList") needs to be called after deleting the item to raise the notification for updating the view .
The ObservableCollection has to interact with the model layer.
Maybe you need this:
https://blogs.msdn.microsoft.com/bethmassi/2009/05/08/using-the-wpf-observablecollection-with-ef-entities/
I have MainWindow thath holds <ContentControl ... Content="{Binding CurrentViewModel}" in MainViewModel I am switching between two View FirstView,SecondView. FirstView contains usercontrol ContentFirstView that implementing async data sending to ContentSecondViewModel. Data send's with time delay 1000ms. The main question is why when i am clicking on 1,2,1,2,1,2 buttons the speed of updating label Count in ContentSecondView greatly increasing? I think that ContentSecondViewModel do not disposing and every time when i am clicking on button 2, it creates new object of Messenger.Register ...
MainModel.xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="1" Content="{Binding CurrentViewModel}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Button Content="1" Command="{Binding FirstCommand}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75"/>
<Button Content="2" Command="{Binding SecondCommand}" HorizontalAlignment="Left" Margin="10,78,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
MainViewModel.cs:
public class MainViewModel : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
///
public RelayCommand FirstCommand
{
get
{
return new RelayCommand(() => SwitchFirst());
}
}
public RelayCommand SecondCommand
{
get
{
return new RelayCommand(()=>SwitchSecond());
}
}
public static readonly FirstViewModel firstViewModel = new FirstViewModel();
public static readonly SecondViewModel secondViewModel = new SecondViewModel();
ViewModelBase currentViewModel;
public ViewModelBase CurrentViewModel
{
get
{
return currentViewModel;
}
set
{
if (currentViewModel == value)
return;
currentViewModel = value;
RaisePropertyChanged("CurrentViewModel");
}
}
public void SwitchFirst()
{
CurrentViewModel = MainViewModel.firstViewModel;
}
public void SwitchSecond()
{
CurrentViewModel = MainViewModel.secondViewModel;
}
public MainViewModel()
{
CurrentViewModel = MainViewModel.secondViewModel;
////if (IsInDesignMode)
////{
//// // Code runs in Blend --> create design time data.
////}
////else
////{
//// // Code runs "for real"
////}
}
}
SecondView.xaml:
<Grid>
<views:ContentSecondView></views:ContentSecondView>
</Grid>
FirstView.xaml:
<Grid>
<views:ContentFirstView></views:ContentFirstView>
</Grid>
ContentFirstView.xaml:
<Grid>
<Label>View That sending data</Label>
</Grid>
ContentSecondView.xaml:
<Grid>
<Label>View That sending data</Label>
</Grid>
ContentFirstViewModel.cs:
public class ContentFirstViewModel
{
public RelayCommand SendMessage
{
get
{
return new RelayCommand(() => Send());
}
}
public void Send()
{
Messenger.Default.Send<MessageCommuniactor>(new MessageCommuniactor {State=1 });
}
public void Increase()
{
while(true)
{
System.Threading.Thread.Sleep(1000);
Messenger.Default.Send<MessageCommuniactor>(new MessageCommuniactor { State = 1 });
}
}
public ContentFirstViewModel()
{
Action A = new Action(Increase);
IAsyncResult result = A.BeginInvoke(null, null);
}
}
ContentSecondViewModel.cs:
public class ContentSecondViewModel:ViewModelBase
{
private int count;
public int Count
{
get
{
return this.count;
}
set
{
this.count = value;
this.RaisePropertyChanged("Count");
}
}
public ContentSecondViewModel()
{
Messenger.Default.Register<MessageCommuniactor>(this, (key) =>
{
Count += key.State;
});
}
}
Your DataTemplate ensures that a new view is created every time a ContentFirstViewModel is present. Instead, go with a singleton approach where a singleton view is injected when needed. You can use Prism's regionmanager or simple binding for that.
This is a silverlight application, Im using asynchronous filtering for an autocompletebox, the problem is that so far i fail to bind FilterAsyncCommand property from the behaviour with the corresponding ViewModel property.
Following is the xaml declaration for the control in the View:
<controls:ChildWindow x:Class="MyApp.Views.View1"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:fw ="clr-namespace:NetBoxSys.Views"
...
>
<sdk:AutoCompleteBox
MinimumPrefixLength="3" MinimumPopulateDelay="150"
SelectedItem="{Binding Path=...}" ItemsSource="{Binding Path=...}" >
<i:Interaction.Behaviors>
<fw:FilterAsyncBehavior FilterAsyncCommand="{Binding Path=FilterAsyncCommand}" />
</i:Interaction.Behaviors>
</sdk:AutoCompleteBox>
</controls:ChildWindow>
...ViewModel code:
private ICommand filterAsyncCommand;
public ICommand FilterAsyncCommand {
get { return filterAsyncCommand; }
set {
filterAsyncCommand = value;
this.OnPropertyChanged( "FilterAsyncCommand" );
}
}
...and this is how im loading the View
var view = new View1();
view.DataContext = new ViewModel1();
view.Show(); //Modal
I have tried this syntax too but does not work either:
<fw:FilterAsyncBehavior FilterAsyncCommand="{Binding FilterAsyncCommand}" />
Need advice for this kind of binding.
UPDATE:
Behaviour code:
public class FilterAsyncBehavior : Behavior<AutoCompleteBox>
{
public ICommand FilterAsyncCommand
{
get
{
return (ICommand)GetValue(FilterAsyncCommandProperty);
}
set
{
SetValue(FilterAsyncCommandProperty, value);
}
}
public static readonly DependencyProperty FilterAsyncCommandProperty = DependencyProperty.Register("FilterAsyncCommand",
typeof(ICommand),
typeof(FilterAsyncBehavior),
new PropertyMetadata(null));
protected override void OnAttached()
{
base.OnAttached();
// handle the populating event of the associated auto complete box
AssociatedObject.Populating += AssociatedObject_Populating;
}
protected override void OnDetaching()
{
// detach the event handler
AssociatedObject.Populating -= AssociatedObject_Populating;
base.OnDetaching();
}
private void AssociatedObject_Populating(object sender, PopulatingEventArgs e)
{
// get the command
ICommand filterCommand = FilterAsyncCommand;
if (filterCommand != null)
{
// create the parameters for the command
var parameters = new FilterAsyncParameters(AssociatedObject.PopulateComplete, e.Parameter);
// execute command
filterCommand.Execute(parameters);
// cancel the population of the auto complete box
e.Cancel = true;
}
}
}
ViewModel code:
public class ViewModel1 : ViewModel, IViewModel {
public ViewModel1() {
//Initializing the command in constructor
FilterAsyncCommand = new DelegateCommand<FilterAsyncParameters>( ExecuteFilterAsync );
}
private void ExecuteFilterAsync( FilterAsyncParameters args ) {
....
}
private ICommand filterAsyncCommand;
public ICommand FilterAsyncCommand {
get { return filterAsyncCommand; }
set {
filterAsyncCommand = value;
this.OnPropertyChanged( "FilterAsyncCommand" );
}
}
}
I find the solution for my problem. I give up with passing the ViewModel at runtime, so i changed to the following implementation of the MVVM pattern
<controls:ChildWindow x:Class="MyApp.Views.View1"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:fw ="clr-namespace:NetBoxSys.Views"
...
>
<controls:ChildWindow.Resources>
<viewModel:ViewModelRecepcionOCViewModelLocator x:Key="viewModelLocator"/>
</controls:ChildWindow.Resources>
<controls:ChildWindow.DataContext>
<Binding Source="{StaticResource viewModelLocator}" Path="ViewModel" />
</controls:ChildWindow.DataContext>
<sdk:AutoCompleteBox HorizontalAlignment="Stretch" Margin="2" x:Name="remitente_Autocomplete" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4"
MinimumPrefixLength="3" MinimumPopulateDelay="150" Padding="0" Height="23" TabIndex="1" Text="{Binding Path=NombreRemitente,Mode=TwoWay}"
SelectedItem="{Binding Path=SelectedRemitente,Mode=TwoWay}" ItemsSource="{Binding Path=Remitentes}" >
<i:Interaction.Behaviors>
<fw:FilterAsyncBehavior FilterAsyncCommand="{Binding Source={StaticResource viewModelLocator},Path=ViewModel.FilterAsyncCommand}" />
</i:Interaction.Behaviors>
</sdk:AutoCompleteBox>
</controls:ChildWindow>
The important part here is the binding definition for FilterAsyncCommand.
And RecepcionOCViewModelLocator is defined like this
public class RecepcionOCViewModelLocator : ViewModelLocatorBase<IRecepcionOCViewModel>
{
public IRecepcionOCViewModel ViewModel{get;set;}
}