RaisePropertyChanged for Windows Phone - windows-phone-7

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.

Related

MVVMCross MvxDialogFragment Restore Issue - Does not have MvxFragmentPresentationAttribute

I have upgraded to the latest version of MvvmCross (6.4.1) from 4.2.3. I and using Xamarin Android not Xamarin forms
In the view which initiates the dialog I do the following
Create dialog fragment derived from MvxDialogFragment
Assign a view model to it
Then call ShowView on the fragment
However when I rotate the device it fails in OnCreate with the message
Your fragment is not generic and it does not have MvxFragmentPresentationAttribute attribute set!
This did not happen in 4.2.3. The reason I create dialog this way is that I want it to use different view models depending on where I need this dialog. For example I want to show a different list of data, but in the same format in the dialog.
It seems this will only work if we apply the MvxFragmentPresentationAttribute which needs the type of view model to be defined at design time rather than run time.
Is there anything I can do to achieve this
Any help will be appreciated
If you somehow need to specify the ViewModel type at runtime, you can instead of decorating the class with the MvxFragmentPresentationAttribute let it implement, IMvxOverridePresentationAttribute and return it there with the appropriate ViewModel to be presented in.
Something like:
public class MyDialog : MvxDialogFragment, IMvxOverridePresentationAttribute
{
public MvxBasePresentationAttribute PresentationAttribute(MvxViewModelRequest request)
{
return new MvxFragmentPresentationAttribute
{
ActivityHostViewModelType = myDynamicType
};
}
}
Where you implement some kind of logic to get the myDynamicType somewhere.
However, you should be able to use MvxDialogFragmentPresentationAttribute instead though and the presenter will attempt to use the topmost Android Activity to present it in if you provide a null ref as the ActivityHostViewModelType.

Processing child Control Events in Windows Forms Components in C++

I am a noob to Windows Forms so this is likely a remedial question. I have a child component with a button and a text field. I want to use multiple instances of these in a parent component or form. At runtime, when the user clicks one of the buttons, I want the parent to get the event to decide what to do with the associated text.
Coming from the long lost world of Borland C++ Builder, during design time, I would simply double-click on the buttons and handlers in the parent would be created which I could just elaborate the code. With Windows Forms, the component controls are not clickable (at design time) from the parent and are "frozen". It is not obvious to me how to pass any child button clicks to a parent. I've tried things like changing the button modifier from private to public but that doesn't help. How is this best accomplished.
Note I am using C++ as I am sharing header file definitions with an associated C++ embedded app.
-Bob
UPDATE:
My apologies, I thought I was still in my C# search :(
This is slightly complicated if you actually want to bubble up an event, or very easy if you use methods.
Methods:
In your child container, add a constructor or property that takes in and stores the parent. Then in the button handler, call this.Parent.ButtonClicked(this); and of course in the parent, add a ButtonClicked(ChildType child) method. That should get you there that way.
Custom Event:
To use events, you need to add a few things. Firstly, add a custom EventArgs class as such:
class ChildClickedEventArgs : EventArgs
{
// include a ctor and property to store and retrieve the child instance.
}
Then add a public delegate for it:
public delegate void ChildClickedEventHandler(object sender, ChildClickedEventArgs e);
Then to your child class, add a ButtonClicked event:
public event ChildClickedEventHandler ChildClicked;
And finally, a helper method to raise it:
private OnButtonClicked()
{
if (this.ChildClicked != null)
{
this.ChildClicked(this, new ChildClickedEventArgs(this));
}
}
Then when you add the child class to the parent, add an event handler for each, and you can handle your custom event for your custom control.
Alternatively:
If you can expose the Button in your child class, simply do the above but register it to this.child.Button.Clicked, saving adding the event handler yourself.

SubreportProcessing event handler cannot access my viewmodel due to being on a different thread

I have a WPF application that is utilizing the reporting tools included with Visual Studio 2010. I've had some other problems that I've solved by creating a graph of objects that are all marked as serializable, etc., as mentioned on various other web pages.
The ReportViewer control is contained in a WindowsFormsHost. I'm handling the SubreportProcessing event of the ReportViewer.LocalReport object to provide the data for the sub report.
The object graph that I'm reporting on is generated in my viewmodel, and that viewmodel holds a reference to it. The SubreportProcessing handler is in my code behind of my window (may not be the best place - but I simply want to get the ReportViewer working at this point).
Here's the problem: In my event handler, I'm attempting to get a reference to my viewmodel using the following code:
var vm = DataContext as FailedAssemblyReportViewModel;
When the handler is called, this line throws an InvalidOperationException with the message The calling thread cannot access this object because a different thread owns it.
I didn't realize the handler might be called on a different thread. How can I resolve this?
I attempted some searches, but all I've come up with is in regards to updating the UI from another thread using the Dispatcher, but that won't work in this case...
I solved this problem using something I believe is a hack, by adding the following function:
public object GetDataContext() {
return DataContext;
}
And then replacing the line of code from my question with:
object dc = Dispatcher.Invoke(new Func<object>(GetDataContext), null);
var vm = dc as FailedAssemblyReportViewModel;
However, this seems like a hack, and I might be circumventing some sort of safety check the CLR is doing. Please let me know if this is an incorrect way to accomplish this.
That's a nasty problem you have there.
Why don't you use in the view a content presenter which you bind to a windows form host?
And in the view model you would have a property of type of type WindowsFormsHost. Also,in the view model's constructor you could set the windows form's host Child property with the report viewer.
After that is smooth sailing, you could use your report viewer anywhere in your code. Something like this:
View:
<ContentPresenter Content="{Binding Path=FormHost}"/>
ViewModel:
private ReportViewer report = new ReportViewer();
private WindowsFormsHost host = new WindowsFormsHost();
public WindowsFormsHost FormHost
{
get {return this.host;}
set
{
if(this.host!=value)
{
this.host = value;
OnPropertyChanged("FormHost");
}
}
}
public ViewModel() //constructor
{
this.host.Child = this.report;
}
After that happy coding. Hope it helps.

Display a custom login control in Windows Phone with Mvvm light

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.

Observe event created through an instance of a Winforms UserControl

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.

Resources