How do I correctly bind? - windows-phone-7

I have a class MyClass, which implements INotifyPropertyChanged, and it has some properties that must be bound in some page. In my page I have
private MyClass myclass;
and in the page constructor I write
ContentPanel.DataContext = myclass;
When I assign myclass to some MyClass object, which I get from some callback, nothing is shown in page.
But when I write the properties that I must change instead of MyClass class in page.cs and bind them it work correctly.
Or when I give
ContentPanel.DataContext = this;
and in xaml I write
{binding this.myclass.property}
it also works correctly.
Here is callback
public void GetCommonInfoCallback(UserCommonInfo userCommonInfo)
{
CommonInfo = userCommonInfo;
}
where UserCommonInfo is MyClass, and CommonInfo is myclass.
private UserCommonInfo userCommonInfo ;
public UserCommonInfo CommonInfo
{
get
{
return userCommonInfo;
}
set
{
if (userCommonInfo != value)
{
userCommonInfo = value;
OnPropertyChanged("CommonInfo");
}
}
}
I can't understand where is my mistake. Can you help me?

When you set DataContext, it is the specific instance of MyClass that is used for data binding. So after executing
ContentPanel.DataContext = myclass;
you could later execute
myclass.someProperty = "new value of someProperty";
and the data will be updated in the bound control (assuming this is not a OneTime binding, but OneWay or TwoWay binding instead).
If I understand you question correctly, you want to change the binding to use a different instance of MyClass.
myclass = new MyClass { /* ... */ }; // new instance of MyClass
At this point, the controls are still bound to the previous instance of MyClass. You can change that by updating the DataContext:
DataContext = myclass; // set context to the new MyClass instance
The second approach that you wrote, with
ContentPanel.DataContext = this;
represents a different style, where you are making the page class also serve as the data model instance for data binding.
In this case, you are not changing the data binding to use a new instance of the data model (the page instance, 'this', is not changing). IMHO, there is very valuable to separate the page and the data model, so I prefer to not use the DataContext = this approach.

Related

Dataview Delegate in Extension not executing

I am attempting to provide a Dataview delegate overide to the UnionDeductions view in PRCalculationEngine.cs
I note that this View does NOT have a defined dataview delegate in the Base graph - and the declaration is a bit 'different' in that is uses a BQL Fluent class.
Is this even possible to introduce a data view delegate in an extension
If so, Is there a different way of declaring the delegate ?
The business case is that the client needs to modify the Amount of the union deduction based on certain Employee attributes (length of service etc) and needs to dynamically modify the amount.
Due to the private and protected access of the GetBenefits and CalculateRegularBenefitNominalAmount methods, the only way I see to do this is to over-ride the dataview delegate and alter the Deduction/Benefit amounts prior to the calculation of the Benefit/Deduction amount...
public partial class PRCalculationEngine : PXGraph
{.....
public UnionDeductionQuery UnionDeductions;
...}
When I attempt to define a dataview delegate for this view in an Extension - I cannot get the dataview delegate to 'fire'
ie The code always just runs the .Select on the Base view but does not execute the delegate.
This is the core of the extension code
public class PRCalculationEngine_Ext1ESP : PXGraphExtension
{
public static bool IsActive() { return PXAccess.FeatureInstalled<FeaturesSet.payrollModule>(); }
#region Select Overrides
public PRCE.UnionDeductionQuery UnionDeductions;
protected System.Collections.IEnumerable unionDeductions()
{
foreach (PXResult<PREarningDetail, PRDeductionAndBenefitUnionPackage, PRDeductCode, EPEarningType> result in
UnionDeductions.Select())
{
// modify the package amount here...
yield return result;
}
}
#endregion
}
This is how the view is being called in the Base Graph
foreach (IGrouping<int?, PXResult<PREarningDetail, PRDeductionAndBenefitUnionPackage, PRDeductCode, EPEarningType>> resultGroup in UnionDeductions.Select(deductionCode.CodeID)
.Select(x => (PXResult<PREarningDetail, PRDeductionAndBenefitUnionPackage, PRDeductCode, EPEarningType>)x)
.GroupBy(x => ((PREarningDetail)x).RecordID))
{
Any advice or observations would be appreciated.
If the requirement is to overwrite the logic of the base dataview delegate which also references other protected methods, try if this helps:
First create an extension of the base class as follows with the PXProtectedAccess attribute and the methods that you want to override:
[PXProtectedAccess]
public abstract class PRCalculationEngine_FirstExt : PXGraphExtension<PRCalculationEngine>
{
[PXProtectedAccess]
public abstract DedBenAmount CalculateRegularBenefitNominalAmount(
PRDeductCode deductCode,
PREmployeeDeduct employeeDeduct,
PRPaymentDeduct paymentDeduct);
}
Then create a second extension (your actual graph extension) inheriting from both the base class and the first extension you created above.
public class PRCalculationEngine_Extension : PXGraphExtension<PRCalculationEngine_FirstExt, PRCalculationEngine>
{
// Here declare the view, write the PXOverride method, and access the protected methods of the base graph by referencing those as Base1.CalculateRegularBenefitNominalAmount()
}
Note that the above snippets are just to give an indication. I have not really worked on the PRCalculationEngine or tested that code but had done similar changes on a different graph to override the dataview delegate. Let me know if it helps. Thank you.

Should I be using BindingBase instead of Binding in the signature of a class that creates a Xamarin Object?

I am creating a new object from my Xamarin code like this:
new ArrowGrid("Group Name", new Binding(nameof(_vm.Name))));
and using it like this:
public ArrowGrid(string text1, Binding text2, string tapCommandParam) : this()
{
this.Text1 = text1;
this.SetBinding(ArrowGrid.Text2Property, text2);
}
ReSharper is suggesting that I change to BindingBase:
public ArrowGrid(string text1, BindingBase text2) : this()
Can someone explain to me what the difference is between Binding and BindingBase. Is there any reason to change to BindingBase?
It is similar You could choose by yourself.
The SetBinding method defined by BindableObject has an argument of type BindingBase from which the Binding class derives.
The following example shows how to set a binding to a property via BindingBase.
var label = new Label ();
label.SetBinding (Label.TextProperty, new Binding ("Name"));
There are other SetBinding methods defined by the BindableObjectExtensions class. It creates and applies a binding to a property.
The following example shows how to use the extension method to set a binding. This is a simpler SetBinding extension method from this class.
var label = new Label ();
label.SetBinding (Label.TextProperty, "Name");

How to set a class wide variable?

Just starting with Swift, I'm creating an API service class but I don't understand how I can make this work!?!
import UIKit
class Hello {
var className: String
init() {
self.className = "hello"
}
class func someFunc() {
println(self.className = "hello") // <= This doesn't work
}
}
From what I understand, since I need someFunc to be accessible when I call it, I need it to have class func. Example, in my view controller, when the user clicks a button, I can do Hello.someFunc().
Thanks in advance for your help.
If you want to allow subclasses to be able to override it:
class var className: String { return "Hello" }
(Note that class variables cannot be stored properties; they must be computed properties.)
Otherwise:
static var className = "Hello"
(static is the same as final class)
You can read more about type properties in the Swift Programming Language book.
Your current println is failing because you're trying to print an assignment, rather than a string. I suspect you meant something more like:
println("ClassName is \"\(className)\"")
Although — having said all of that — if you just want to get the name of the class you ought to use:
println(self.dynamicType)
You would need to declared class variable as static that way, you can access it inside your class level methods using self. However, if you want to access that from instance method you will have to use class name with it.
class Hello {
static var className: String = ""
init() {
Hello.className = "hello"
}
class func someFunc() {
println(self.className = "hello")
}
}
Also notice that swift expects that the class variable are initialized when they are created.

Non-static method cannot be referenced from a static context

I'm trying to call a method from another class and from what I've gathered, the method I'm trying to call is an instance method. I've gathered that, that means it uses instance variables of an object. Is there an easy way to call this method?
This is the main method,
public void main()
{
Test.testPetOwner();
}
And this is the method I'm trying to call in a class called "Test"
public void testPetOwner()
{
String petName;
String species;
String hairCondition;
String posture;
testCompetitor();
PetOwner petOwner1 = new PetOwner();
System.out.println("What is the pet's name?");
petName = Genio.getString();
petOwner1.setPetName(petName);
System.out.println("What is the species of the pet?");
species = Genio.getString();
petOwner1.setSpecies(species);
System.out.println("What is the hair condition of the pet?");
hairCondition = Genio.getString();
petOwner1.setHairCondition(hairCondition);
System.out.println("How is the pet's posture?");
posture = Genio.getString();
petOwner1.setPosture(posture);
}
public void main()
{
Test t = new Test();
t.testPetOwner();
}
If we try to access an instance method from a static context , compiler has now way to guess which instance method ( variable for which object ), you are referring too. Though you can always access it using object reference.

How can I apply the "move method" refactoring with IntelliJ IDEA?

I want to be able to move an instance method from one class to another class ("Move method" from Fowler's "Refactoring") in IntelliJ IDEA. Unfortunately, when I try "Move..." (cmd: F6), it tells me that "There are no methods that have a reference type. Would you like to make method static and then move?" I do not want to make my method static, I want it to be an instance method on the other class instead.
My code example:
public class TheClass {
public void doStuff(){
int i = themethod();
}
private int theMethod() {
System.out.println( "Hello World!" );
return 0;
}
}
public class OtherClass {
}
Say I want to move theMethod from TheClass to OtherClass. Is there an automatic refactoring in IDEA for this, and if so: How do I apply it?
In IntelliJ 14-15 do the following:
Position the caret on theMethod().
press Ctrl/Cmd+F6 (Change signature).
Introduce new parameter: Type=TheOtherClass, Name=theOtherClass, Default value=new TheOtherClass()
Refactor
Then press F6 (move) and move the method to theOtherClass.
You will end up with:
public class TheClass {
public void doStuff() {
int i = new TheOtherClass().theMethod();
}
}
public class TheOtherClass {
int theMethod() {
System.out.println("Hello World!");
return 0;
}
}
The Move Method refactoring in IDEA only considers moving the method into classes related to it, i.e. used as its parameter or return value, or called from inside the method. Which is kinda logical: if the method has nothing concrete to do with the target class, why should it be there? OTOH I found this limiting in some cases where I still had a valid reason to move the method. So I had to do it by hand.
In intellij 13.1 (dont' know in previous version) it could be done with the
Choose Refactor | Extract | Delegate on the main menu
but there is a "strange" limit, apparently: it could be done only with a new freshly created class.
So you have to do apply this refactoring without creating the "OtherClass" (it will be create directly when you apply the refactoring).
So a real "move" of method on an alredy created class seems missing, quite strange behaviou
if theMethod() has nothing reference to the host class(TheClass), you can make this method static and then use "Move" command. After the method was moved to the target class, you should remove the static keyword.
There is another method. Imagine you have the code:
public int field;
public void foo(int a) {
assert field == a;
}
And you want to make foo static. Select the whole body of the method and preess Alt+Ctrl+M (Extract method). Type the same name of the method. Check "Declare static" checkbox (available only if the method only reads and doesn't modify the fields) and press Ok. So you get:
public void foo(int a) {
foo(a, field);
}
private static void foo(int a, int field) {
assert field == a;
}
Move static method wherever you want and use old foo's body to call it.

Resources