Share data in paged based interface in Watchkit - watchkit

I need to share a string with all the pages from the first page.
I was trying to do this with didDeactive() but its not working.
Is it possible to even do this?

It's a bit difficult to tell what you are really trying to do, so I'm going to infer a bit. I "think" you are trying to set some shared value from the first page and be able to use that value in other pages. If that's the case, then you could do something like the following:
class SharedData {
var value1 = "some initial value"
var value2 = "some other initial value"
class var sharedInstance: SharedData {
struct Singleton { static let instance = SharedData() }
return Singleton.instance
}
private init() {
// No-op
}
}
class Page1InterfaceController: WKInterfaceController {
func buttonTapped() {
SharedData.sharedInstance.value1 = "Something new that the others care about"
}
}
class Page2InterfaceController: WKInterfaceController {
#IBOutlet var label: WKInterfaceLabel!
override func willActivate() {
super.willActivate()
self.label.setText(SharedData.sharedInstance.value1)
}
}
The SharedData object is a singleton class that is a global object. Anyone can access it from anywhere. In the small example I provided, the Page1InterfaceController is handling a buttonTapped event and changing the value property of the SharedData instance to a new value. Then, when swiping to Page2InterfaceController, the new value is being displayed in label.
This is a super simple example of sharing data between objects. Hopefully that helps get you moving in the right direction.

Related

WF 4 Rehosted Designer - get foreach InArgument Value

After reading this article:
http://blogs.msdn.com/b/tilovell/archive/2009/12/29/the-trouble-with-system-activities-foreach-and-parallelforeach.aspx
I have defined the ForEachFactory as follows:
public class ForEachFactory<T> : IActivityTemplateFactory
{
public Activity Create(DependencyObject target)
{
return new ForEach<T>
{
DisplayName = "ForEachFromFactory",
Body = new ActivityAction<T>
{
Argument = new DelegateInArgument<T>("item")
}
};
}
}
All works well but is it possible to check how that DelegeateInArgument in my case named "item" changes its value ?
So if i have defined an array in the variables section and initialized with
{1, 2, 3} i need a way to check how the "item" takes value 1, 2 and then 3.
To be more accurate, i've added this pic, with a breakpoint on the WriteLine activity inside the foreach. When the execution will stop there, is there a way to find out what the value of item is ?
EDIT 1:
Possible solution in my case:
After struggling a bit more i found one interesting thing:
Adding one of my custom activities in the Body of the ForEach, i am able to get the value of the item like this :
So, my activity derives from : CodeActivity
Inside the protected override String[] Execute(CodeActivityContext context) i am doing this job.To be honest, this solves the thing somehow, but it is doable only in my custom activities. If i would put a WriteLine there for example, i would not be able to retrieve that value.
you can access the DelegeateInArgument of a ForEach activity by inspecting the ModelItem trees parent and checking for DelegeateInArgument's. If you need a specific code example to achieve this I may need a some time to code the example. As it has been a long time since I did this, see my question i asked over on msdn
So basically where your break point is, you can access the variable values as these are defined with n the scope of your activity as 'variables'. However the 'item' variable is actually only accessible from the parent loop activity. So you have to get the model item of the current executing activity and then traverse up the tree to find the parent containing the desired DelegateInArgument.
Can you flesh out exactly what you want to achieve? Is it that when your debugging the workflow in the re-hosted designer you want to display the variable values to the user as they change in the UI?
Edit - added tracking example
So as your wanting to display the variable values during execution of the workflow we need to use tracking to achieve this. In the example your using the author has already implemented some basic tracking. So to achieve the extended variable tracking you want you will need to alter the tracking profile.
Firstly amend the WorkflowDesignerHost.xaml.cs file alter the RunWorkflow method to define the SimulatorTrackingParticipant as below.
SimulatorTrackingParticipant simTracker = new SimulatorTrackingParticipant()
{
TrackingProfile = new TrackingProfile()
{
Name = "CustomTrackingProfile",
Queries =
{
new CustomTrackingQuery()
{
Name = all,
ActivityName = all
},
new WorkflowInstanceQuery()
{
**States = {all },**
},
new ActivityStateQuery()
{
// Subscribe for track records from all activities for all states
ActivityName = all,
States = { all },
**Arguments = {all},**
// Extract workflow variables and arguments as a part of the activity tracking record
// VariableName = "*" allows for extraction of all variables in the scope
// of the activity
Variables =
{
{ all }
}
}
}
}
};
This will now correctly capture all workflow instance states rather than just Started/Completed. You will also capture all Arguments on each activity that records tracking data rather than just the variables. This is important because the 'variable' were interested in is actually (as discussed earlier) a DelegateInArgument.
So once we have changed the tracking profile we also need to change the SimulatorTrackingParticipant.cs to extract the additional data we are now tracking.
If you change the OnTrackingRecordReceived method to include the following sections these will capture variable data and also Argument data during execution.
protected void OnTrackingRecordReceived(TrackingRecord record, TimeSpan timeout)
{
System.Diagnostics.Debug.WriteLine(
String.Format("Tracking Record Received: {0} with timeout: {1} seconds.", record, timeout.TotalSeconds)
);
if (TrackingRecordReceived != null)
{
ActivityStateRecord activityStateRecord = record as ActivityStateRecord;
if (activityStateRecord != null)
{
IDictionary<string, object> variables = activityStateRecord.Variables;
StringBuilder vars = new StringBuilder();
if (variables.Count > 0)
{
vars.AppendLine("\n\tVariables:");
foreach (KeyValuePair<string, object> variable in variables)
{
vars.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", variable.Key, variable.Value));
}
}
}
if (activityStateRecord != null)
{
IDictionary<string, object> arguments = activityStateRecord.Arguments;
StringBuilder args = new StringBuilder();
if (arguments.Count > 0)
{
args.AppendLine("\n\tArgument:");
foreach (KeyValuePair<string, object> argument in arguments)
{
args.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", argument.Key, argument.Value));
}
}
//bubble up the args to the UI for the user to see!
}
if((activityStateRecord != null) && (!activityStateRecord.Activity.TypeName.Contains("System.Activities.Expressions")))
{
if (ActivityIdToWorkflowElementMap.ContainsKey(activityStateRecord.Activity.Id))
{
TrackingRecordReceived(this, new TrackingEventArgs(
record,
timeout,
ActivityIdToWorkflowElementMap[activityStateRecord.Activity.Id]
)
);
}
}
else
{
TrackingRecordReceived(this, new TrackingEventArgs(record, timeout,null));
}
}
}
Hope this helps!

Dart Language: observable

I have two table rows at an HTML file. When the first row gets clicked, it changes its styling via classes.add("active_style"). If the second row gets clicked, I would like to clear the first row styling.
I know that I can just write...
querySelector("#first_row_div").classes.clear();
... in order to clear the first row class (and then resetting its style), but in a bigger code I think that observable would be the best fit.
I don't know if observable works for this. But, if it does, how can I do that?
EDIT/UPDATE: I think that the right question is "is there any way to run a function when a variable gets changed?".
Thanks for the help!
You can make a getter/setter for a field and run your function in the setter.
class MyClass {
String _cssClass;
String get cssClass => _cssClass;
set cssClass(String newClass) {
_cssClass = newClass;
updateDom();
}
void updateDom() {
// do important work here
}
}
You can use a model class that extends Observable.
Here you have to call dirtyCheck() to make Observable check for changes and notify listeners.
Dart also offers the ChangeNotifier mixin. Here you don't need to call any method for dirty-checking. When changes are made listeners are invoked.
A simple example I wrote a while ago while examining the functionality
import 'package:observe/observe.dart';
class Notifiable extends Object with ChangeNotifier {
String _input = '';
#reflectable
get input => _input;
#reflectable
set input(val) {
_input = notifyPropertyChange(#input, _input, val + " new");
}
Notifiable() {
this.changes.listen((List<ChangeRecord> record) => record.forEach(print));
}
}
class MyObservable extends Observable {
#observable
String counter = '';
MyObservable() {
this.changes.listen((List<ChangeRecord> record) => record.forEach(print));
}
}
void main() {
var x = new MyObservable();
x.counter = "hallo";
Observable.dirtyCheck();
Notifiable notifiable = new Notifiable();
notifiable.input = 'xxx';
notifiable.input = 'yyy';
}

flex: referencing class variables

I have a bunch of variables in a class. There are situations when I want to set then to null/ "temp" etc as per a well defined logic. The challenge is to list out the variables at multiple places- tedious and error-prone.
classname.speed=NaN
classname.speedtype="not_set"
classname.distance=NaN
classname.distancetype="not_set"
Ideally, would prefer a way to refer to these variables programatically and set something like
"for all class variables- if variable ends in type, set as "not_set"; for other variables set as NaN
How can I achieve this? Any pointers will help
The simplest approach would be just write function to clear them all.
If you want something more automatic, it will requre efforts - look at introspection api. Basically, you call describeType on your class and it returns XML description. All variables will be listed there, along with other info. Then you can parse returned XML and set all variables to needed value, accessing them dynamically with square bracket syntax:
var myClass:MyClass = new MyClass();
myClass["varName"] = "new value";
It can be achieved through Inheritance i.e. implementing interface or extending class
which contains common fields
public class MyClass
{
public a:String = null;
public b:String = null;
public function MyClass()
{
}
}
which contains common var and Child Class could be
public class MyClassChild extends MyClass
{
public var c:String = null;
public function MyClassChild()
{
super();
this.a ="";
this.b ="";
}
}
and you can cast or use for each loop to set values
var temp:MyClassChild = new MyClassChild ();
MyClass(temp).a = "Hello World";
Hopes that helps

Flex combo box labelfunction

I have two questions regarding the Flex combo box.
The string representing the function name will be read from xml # run time.
var combo:ComboBox = new ComboBox();
combo.labelFunction = "functionName";
How can I achieve this?
So the first name, which is to be displayed in the combo box, can be only retrieved by accessing another DTO, called person and then its first name.
var combo:ComboBox = new ComboBox();
combo.labelField= "person.firstName";
My class looks like this,
public class Test
{
public var person:PersonDTO;
}
public class PersonDTO
{
public var firstName:String;
}
Is it possible to access any multi-level text using the combo box label field ?
You need to pass the function not the name.
Doing this
combo.labelFunction = "functionName";
Is passing a string.
The only work around I can think of is to make a switch statement with one case for each function you may have. Then call that with "case" from within your xml.
switch( xml.#labelfunction ){
case 'func1':
combo.labelFunction = this.func1;
break;
case 'func2':
combo.labelFunction = this.func2;
break;
}
Its hacky but should work.
ad 1) labelFunction
Calling functions when you know only the name as String is quite easy. The following snippets shows how you can execute a function that is a member of the same class. In case you need to call a function from another class replace this with the according variable name.
private function comboBox_labelFunction(item:Object):String
{
var functionName:String = myXml.#labelFunctionName;
return this[functionName](item);
}
ad 2) labelField
It's normally not possible to use "person.firstName" as labelField. However, you should be able use it within your labelFunction. Something like this should work...
private function comboBox_labelFunction(item:Object):String
{
var labelField:String = "person.firstName";
var attributeNames:Array = labelField.split(".");
for each (var attributeName:String in attributeNames)
{
if (item && item.hasOwnProperty(attributeName))
item = item[attributeName];
else
return null;
}
return item;
}

Passing values between functions

Hi All is there any way to locally define a variable in a function and then pass it to the oher function. I mean to say is it possible the pass a local value from one function to other function.
Somebody Please suggest me the solution.
Thanks in advance
Or it's that simple or you meant something else:
private function function1():void
{
var localVariable:String = "this is local variable of function1()";
function2(localVariable);
}
private function function2(string:String):void
{
trace(string);
}
function1();
or use global variable as temporary storage:
private var globalVariable:String = "";
private function function1():void
{
var localVariable:String = "this is local variable of function1()";
globalVariable = localVariable;
}
private function function2():void
{
trace(globalVariable);
}
function1();
function2();
zdmytriv is right.
Although, you can also make default variables, like so:
(Modifying zdmytriv's code)
private function function1():void
{
var localVariable:String = "this is local variable of function1()";
function2(localVariable);
function2(); //You don't have to enter a default argument
}
private function function2(string:String = "something else"):void
{
trace(string);
}
This would trace:
this is local variable of function1()
something else
A little off topic, but good to know.
Primitives in Flex are passed by value, where complex objects are passed by reference. You can use this to pass objects around without scoping a variable outside the functions themselves. For instance:
private function function1():void {
{
var localVar:Object = {value:"test"};
trace(localVar.value);
function2(localVar);
trace(localVar.value);
}
private function function2(obj:Object):void
{
obj.value = "new value";
}
This would trace:
test
new value
Which reflects the fact that function2 receives the parameter "obj" by reference, as a pointer to the original "localVar" object. When it sets the .value field, that change is reflected in function1.
I just thought I'd point that out.

Resources