What is the 'smart and direct' way to set some Form variable values from another sub-form.
Say I have mainForm that contains myVar (network port number for example) and settingsButton which when clicked shows another form settingsForm that aims to set myVar....
since settingsForm can't return things other than DialogResult how can I achieve it.
I used to implement it by passing the mainForm instant to settingsForm in its constructor to access its data members as follows:
//////mainForm.h:
#include "settingsForm.h"
...
ref class mainForm: puplic Form
{
puplic:
int myVar;
private: void settingsButton_Click(Object^ sender, EventArgs^ e)
{
(gcnew settingsForm(this))->ShowDialog();
}
...
};
....
////////settingsForm.h
...
ref class mainForm; //forward declaration to avoid circular dependency
ref class settingsForm:public Form
{
mainForm^ mf;
settingsForm(mainForm form)
{
....
mf=form;
}
void okButton_click(Object^ sender, EventArgs^ e); //definition in the cpp file
...
};
///////settingsForm.cpp
...
void settingsForm::okButton_click(Object^ sender, EventArgs^ e)
{
mf->myVar= someValue;
}
...
You could use an event or a shared area to exchange data between them.
But I think your own way is simple and better.
Why are you looking for another way?
Related
I have a simple table [form:tabView:remTNtableID], with a list of strings CFSnumbers, and when I click a button I call getTelephoneNumbers() to fill it, which takes a while.
I'd like to have the table show "Loading.." while waiting, and for that purpose I cleared the list, added "Loading.." to the list, and called RequestContext.getCurrentInstance().update("form:tabView:remTNtableID").
But the table is not updated immediately, "Loading.." is not seen, and only when the getTelephoneNumbers() call ends is the table updated.
What's up? How can I force the table to be re-rendered immediately?
private List<String> CFSnumbers;
#PostConstruct
public void init() throws GuiException {
CFSnumbers = new ArrayList<String>();
}
public void getTelephoneNumbers() throws GuiException {
CFSnumbers.clear();
CFSnumbers.add("Loading..");
RequestContext.getCurrentInstance().update("form:tabView:remTNtableID");
try {
...
CFSnumbers = ...
RequestContext.getCurrentInstance().update("form:tabView:remTNtableID");
} catch (Exception e) {
CFSnumbers.clear();
RequestContext.getCurrentInstance().update("form:tabView:remTNtableID");
}
The action getTelephoneNumbers() is a single request. All updates are executed (send in the response) when your method has been fully executed.
What you could do is split your action into a reset part and a heavy loading part. When you click the button, call reset which resets and updates your table saying "Loading...". When the reset is completed, use a remoteCommand to start the actual heavy loading, and update the table when it completes.
So, in your XHTML:
<p:remoteCommand name="getTelephoneNumbersRemoteCommand"
action="#{yourBean.getTelephoneNumbers}"
update="remTNtableID"/>
<p:commandButton ...
action="#{yourBean.preGetTelephoneNumbers}"
update="remTNtableID"
oncomplete="getTelephoneNumbersRemoteCommand()"/>
And in your bean:
public void preGetTelephoneNumbers() {
CFSnumbers.clear();
CFSnumbers.add("Loading..");
}
public void getTelephoneNumbers() {
try {
...
CFSnumbers = ...
} catch (Exception e) {
CFSnumbers.clear();
}
}
Updating from your bean is no longer necessary, as it is done in the XHTML.
Related:
Is it safe to start a new thread in a JSF managed bean?
I have a command which interacts with an API. If the command doesn't return a desired result it sets a property of the ViewModel called Error.
I want to bind Error to a UIAlertController in my View and have it display when the error occurs.
Here's roughly what I have (although obviously the visibility converter isn't the way to go). I should add that I'm aware PresentViewController should be used to display the UIAlertController.
UIAlertController myAlert = UIAlertController.Create ("", Error.Text, UIAlertControllerStyle.Alert);
set.Bind(myAlert).For("Visibility").To((myViewModel vm) => vm.Error).WithConversion("Visibility");
Check out Observer design pattern.
The way I prefer to achieve that is simple:
Create class which inherits from MvxMessage - let say ShowAlertDialogMessage with properties like title, content and so on.
Create abstract MessageObserver where TMessage : MvxMessage class, ex.:
public interface IMessageObserver
{
void Subscribe(IMvxMessenger messenger);
void Unsubscribe();
}
public abstract class MessageObserver<TMessage> : IMessageObserver where TMessage : MvxMessage
{
public void Subscribe(IMvxMessenger messenger) {
messenger.SubscribeOnMainThread<TMessage>(OnMessageDelivered);
}
public abstract void OnMessageDelivered(TMessage message);
}
Create MessageObserverController
public class MessageObserverController {
public void SubscribeObserver(IMessageObserver msgObserver) {
msgObserver.Subscribe(messenger);
}
.. unsubscribe, dispose and so on goes here
}
Implement ShowAlertDialogMessageObserver class (inherit from MessageObserver<ShowAlertDialogMessage>() which shows UIAlertViewController with data from ShowAlertDialogMessage (title, content and so on). Pass root UIViewController as constructor if needed (you will register MessageObservers in your viewcontrollers anyway - so that's not a problem).
Use MessageObserverController in your ViewControllers (preferably create base view controller to simplify things).
VoilĂ - you get reusable UI logic, which you can raise by publishing message in your PCL ViewModel (without creating any platform-specific coupling!).
I have two ViewModels, the first has a list of type ProductViewModel, this list of type ProductViewModel is backed by a list of type Product in my model.
public List<ProductViewModel> Products
{
get
{
return (from product in ProductManager.Products
select new ProductViewModel(product)).ToList();
}
}
My first ViewModel will add products to the ProductManager.Products list and then raise a PropertyChanged notification so that the UI is updated. (So far so good).
A navigation to a second page then occurs, this then accesses the ProductManager.Products, once these products are processed, the ProductManager.Products list is cleared (by the second ViewModel).
Upon navigating back to the first view, how would I then update the List Products binding?
I am using the ViewModelLocator as provided by MVVMLight and therefore do not have static access to the first ViewModel from the second.
My current workaround is to create a BaseView page, override the OnNavigatedTo method, raise an event in this override, which I can then bind a Command to in my first ViewModel so that I can then call RaisePropertyChanged.
public class BaseView : PhoneApplicationPage
{
public event RoutedEventHandler NavigatedTo;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigatedTo != null)
{
NavigatedTo(this, new RoutedEventArgs());
}
}
}
<i:EventTrigger EventName="NavigatedTo">
<cmdextras:EventToCommand Command="{Binding Path=PerformNavigatedTo}" />
</i:EventTrigger>
public ICommand PerformNavigatedTo
{
get
{
return new RelayCommand(
() =>
{
RaisePropertyChanged(() => Products);
RaisePropertyChanged(() => SecondaryPageName);
},
() => true);
}
}
In addition to my workaround above, I previously investigated implementing messaging between ViewModels. Unfortunately this wasn't working for me as I had forgotten to include the Token when calling the Register method. As soon as I sorted this out I was able to send a message from the second ViewModel to be received by the first and therefore call the RaisePropertyChanged method as required.
Also, as soon as I realised that SimpleIoC returned the same instance after multiple calls to GetInstance, this helped in my understanding.
I am using windows programming with C++ and have below code:
class A
{
public:
virtual void Func1 () {}
void Func2 () {}
}
class B : public A
{
public:
__override virtual void Func1 () {}
}
I made a double linked list of B objects using LIST_ENTRY and tried to visit an element in this list in below way:
LIST_ENTRY * pEntry; // I got this pointer using RemoveHeadList
A * pA;
pA = CONTAINING_RECORD (pEntry, A, m_le);
pA->Func2 (); // works fine
pA->Func1 (); // Access violation
As you see, the pointer retrieved using CONTAINING_RECORD cannot call a virtual function. What could be wrong? Thanks for any help.
From what I can see in the code, CONTAINING_RECORD is returning an invalid pointer. Show us the code for it. Func2 wprks just by chance, because is not dependant on the this pointer, but is nevertheless ilegal.
Any one know how to bind one swing JComponent to two BeansBinding classes(Specially with Netbeans IDE)? Also how to bind a variable in JFrame to a beanbinding class's property?
A) Hmm ... still not sure what exactly you want to achieve: build a binding chain, maybe? Something like
bean."name" <--> textField."text" --> otherBean.logger
BindingGroup context = new BindingGroup();
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ_WRITE,
bean, BeanProperty.create("name"),
field, BeanProperty.create("text")));
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ,
field, BeanProperty.create("text"),
otherBean, BeanProperty.create("logger")));
B) Beansbinding is all about binding properties not fields (aka: variables). So whatever you want to bind needs a getter and (maybe a setter, depends on your requirements) and must fire notification on change. Then do the binding just as always ..
public MyFrame extends JFrame {
private int attempts;
public int getAttempts() {
return attempts;
}
private void incrementAttempts() {
int old = getAttempts();
attempts++;
firePropertyChange("attempts", old, getAttempts());
}
private void bind() {
BindingGroup context = new BindingGroup();
context.addBinding(Bindings.createAutoBinding(UpdateStrategy.READ,
this, BeanProperty.create("attempts"),
label, BeanProperty.create("text")));
}
}