How can i move
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
to the viewmodel and still be able to control "back'ing"? In the codebehind, i can use e.Cancel = true;, but how to use it in the viewmodel?
You can't bind something that isn't bindable per say. All you can do is either create a fake binding using a Behavior<T>, but not much point in that.
Instead you could just simply forward the event in the ViewModel, doing something like:
e.OnCancel = ViewModel.OnBackKeyPress();
And then have OnBackKeyPress() return a bool.
The very first idea that i got - is to leave it in codebehind, and send message to viewmodel, so it should shange its state. But i'd still prefer to bind event to VM.
Related
I have a Xamarin Forms app where I use the Master-Detail template, in combination with MVVM. It suites my needs quite well. The thing is that I would occasionally show some sort of information in a notification-like style in the top bar of the displayed view. This would sometimes be an error message like "Server not reachable" or "Action not allowed".
The thing is that it seems the only way to put something into that bar is via the ContentPage.ToolbarItems, which does not have a DataBinding or any way to be accessed via the ViewModel.
A possible solution I came up with is passing the view as an argument to the ViewModel, and from there do something like view.ToolbarItems.Add(new ToolbarItem("abc", null, () => { }));. But this is breaking the MVVM on a quite basic level, as the ViewModel has a reference to the View. It would be possible to mask the view with an interface, but I don't like this solution at all.
So, can I use DataBinding to dynamically add and remove a button to the top bar in a Xamarin Master-Detail app?
As you have already mentioned, it is never a good idea to have a reference to the view in the viewmodel because it breaks the MVVM pattern. In cases like yours, when binding is not available, a sensible/acceptable approach is to subscribe to the viewmodel from the view in order to update it if the viewmodel changes.
Add something like this to your view:
ViewModel.PropertyChanged += OnViewModelPropertyChanged;
...
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(ViewModel.YourProperty):
// Apply changes to the view here, for example:
ToolbarItems.Add(new ToolbarItem(ViewModel.YourProperty, null, () => { }));
break;
}
}
I hope this helps!
How to raise a click event manually for a button in windows phone ?
Is it possible technically ? And is that a good suggestion to raise such event manually ?
You can raise events manually just like with any other function, since per-se, an event handler is nothing but a function that is associated with data passed to it in case of an event.
So, let's say you have a mock event handler:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Debug.WriteLine("TEST");
}
You can easily invoke it manually with:
Button_Click_1(btnTest, new RoutedEventArgs());
In this case, you can supply your own sender. If you want to raise an event specifically, without having to explicitly bind to your own event handler, take a look at this answer - you can use Reflection, although I am not sure why you'd need it like that.
Ok, so what I am looking to do is to display some sort of login control (maybe a UserControl with a TextBox and PasswordBox) when the app is started.
In a non-mvvm situation, a way of doing this would be to use the PopUp primitive control, add the usercontrol as a child element and off you go.
In an MVVM situation, i'm a bit confused about how you would achieve a simmilar result.
I have looked into messaging with the DialogMessage and this is fine for displaying a typical MessageBox, but what about a custom usercontrol?
any help would be fantastic! I can't seem to find any demo code of this anywhere.
In a MVVM situation you can use a delegate to let your View open the dialog when the ViewModel requests it.
You define a delegate at the VM:
public Func<LoginResult> ShowLoginDialogDelegate;
In your View you define the function that will be called:
private LoginResult ShowLoginDialog()
{
LoginResult result;
// show a dialog and get the login data
return result;
}
Then you "connect" the delegate and method in the View:
_viewModel = new MyViewModel();
DataContext = _viewModel;
_viewModel.ShowLoginDialogDelegate += ShowLoginDialog;
And now you can use it in your ViewModel e.g. when a command is executed like that:
LoginResult result = ShowLoginDialogDelegate();
An easier answer is to control it's visibility through a View State which with a little manipulation can be made to work through databinding allowing the view model to display the "Logon Page" state when required.
I just recently wrote about this for the Silverlight/XNA series which you can view here.
It would be much simplier if the SL4 DataEventrigger was available but hay ho.
I'm starting to use the MVVMLight framework and have a question about binding to properties in the ViewModel. I found that I have to call the RaisePropertyChanged method in the setter for the property in order for the View to be updated. And I have to call RaisePropertyChanged from through the dispatcher otherwise I get a thread access error.
public string Lat { get { return _lat; } set
{
_lat = value;
Deployment.Current.Dispatcher.BeginInvoke(() => RaisePropertyChanged("Lat"));
} }
This works but its a lot of code to get auto binding properties. Is there a helper to handle this more cleanly?
Raising PropertyChanged events is mandatory when you want to bind UI elements to properties on your model classes, independently of whether you're using MVVM Light or not. In fact it's easier with MVVM Light as it provides the RaisePropertyChanged method, which you would otherwise have to code yourself. :)
Using Dispatcher.BeginInvoke() is only needed if the set accessor of your property can be invoked from a thread different from the UI thread. Otherwise it's OK to call RaisePropertyChanged directly.
In my winforms app, I have a UserControl that contains a DataGridView. I instantiate and load this UserControl when needed into a panel in my Main Form (frmMain). My problem is figuring out how to resond to or listen for events raised in my UC's DataGridView. For example, I want to handle the CellDoubleClick event of the DataGridView in my Main Form rather than through the UC.
Is this possible? I had thought of updating a property when the cell in the grid is double-clicked, and then let my Main form do whatever when that property changes - therefore I thought of using INotifyPropertyChanged. Im not heavily clued up on how to use it in m scenario however, and would deeply appreciate some help in this regard, or if anyone can suggest an alternate solution.
Much thanx!
Your user control must encapsulate some logic, so if you want to handle event of the DataGridView that is in your control the way you've described, you probably missing something in idea of user controls and encapsulation. Technically here two ways to do this:
Make a public property in your user control of type DataGridView.
Make an event wrapper. You will need to create an event in your user control that is raised when DataGridView CellDoubleClick (or any) is rased and in your calling code you will handle this event wrapper.
The second approach is more logical, cos internal logic of your control is incapsulated and you can provide end-user of you component with more logical and meaningful event then CellDoubleClidk or else.
thank u 4 your reply. Sorry for not responding earlier. I did manage to sort this issue out by creating a public event in my UC:
public event DataGridViewCellEventHandler GridRowDoubleClick {
add { dgvTasks.CellDoubleClick += value; }
remove { dgvTasks.CellDoubleClick -= value; }
}
and in my main form, after I instantiate and load the UC
_ucTask.GridRowDoubleClick += new DataGridViewCellEventHandler(TasksGrid_CellDoubleClick);
with the following attached event:
private void TasksGrid_CellDoubleClick( object sender, DataGridViewCellEventArgs e ) {
// do work here!
}
This does work, although I don't know if any of u experts out there foresee a problem with this approach.