Simple databinding IN CODE to a DependencyProperty - data-binding

My apologies as this is simplistic enough I know the question's been answered but in 30 or so pages, I've yet to find the boiled down problem I'm trying to solve.
I'm not yet well practiced in SL and trying a simple version of attempting to write a TextBox that binds to a property within the screen and updates it when Text is altered and vice versa (property change propagates to the Text). Due to a few reasons, I need to do this with DependencyProperties and in the codebehind rather than INotifyPropertyChanged and in XAML.
My latest attempts look something like this:
public partial class MainPage : UserControl
{
static MainPage()
{
TargetTextProperty = DependencyProperty.Register("TargetText", typeof(string), typeof(MainPage), new PropertyMetadata(new PropertyChangedCallback(TextChanged)));
}
public readonly static DependencyProperty TargetTextProperty;
public string TargetText
{
get { return (string)GetValue(TargetTextProperty); }
set { SetValue(TargetTextProperty, value); }
}
public MainPage()
{
InitializeComponent();
TargetText = "testing";
textBox1.DataContext = TargetText;
Binding ResetBinding = new Binding("TargetText");
ResetBinding.Mode = BindingMode.TwoWay;
ResetBinding.Source = TargetText;
textBox1.SetBinding(TextBox.TextProperty, ResetBinding);
}
private static void TextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MainPage pg = (MainPage)sender;
pg.textBox1.Text = e.NewValue as string;
}
}
Anyone see what (painfully obvious thing?) I'm missing?
Thanks,
John

The following should be enough to set the binding you want:
textBox1.SetBinding(TextBox.TextProperty, new Binding() { Path = "TargetText", Source = this });
The problem with your code is that you set both Source and binding Path to the TargetText property and as a result you get the framework trying to bind to TargetText.TargetText, which is obviously wrong.

Related

Xamarin.Forms Update Label Text From a Service

I have a Label on MainPage.xaml. I can edit Label Text from MainPage.xaml.cs.
There is a foregroung service running as well. There is function in this service to check a value from SQLite DB for every 10 secs. When value changes, Label text should be updated. I tried binding but it is a bit confusing. I manage updating by using like this: (foreground service timer changes App.SomeValue)
protected override void OnAppearing()
{
lblSyncID.Text = App.SomeValue;
}
But I need to see changes without OnAppearing or any other navigation change.
EDIT:
With #Jason's suggestion I used Messaging Center (and also binding) and it works now:
MainPage.xaml:
<Label Text="{Binding AppWaitingRecordValue}" ...
MainPage.xaml.cs:
public partial class MainPage : ContentPage
{
private string appWaitingRecordValue;
public string AppWaitingRecordValue
{
get { return appWaitingRecordValue; }
set
{
appWaitingRecordValue = value;
OnPropertyChanged(nameof(AppWaitingRecordValue));
}
}
public MainPage()
{
InitializeComponent();
BindingContext = this;
AppWaitingRecordValue = "0";
MessagingCenter.Subscribe<App>((App)Application.Current, "AppRecord", (sender) =>
{
AppWaitingRecordValue = App.recordWaiting.ToString();
});
}
.
.
TimestampService.cs (from Project.Android):
// get i from DB
App.recordWaiting = i;
Xamarin.Forms.MessagingCenter.Send<App>((App)Xamarin.Forms.Application.Current, "AppRecord");

DisplayAlert from ViewModel not displaying

I need to display DisplayAlert from the View Model, however its simply doesn't display. Is there some other way how to display alert from the VM? The permission is true so that works.
private async Task TakePicture()
{
await Permission();
var imageSource = Application.Current.MainPage.DisplayActionSheet(AppResources.AlertNewPhoto, AppResources.AlertNewPhoto, AppResources.AlertGallery);
if (imageSource.Result == AppResources.AlertNewPhoto)
}
You can change your constructor of ViewModel like following code.
public PersonsViewModel(ContentPage page){
page.DisplayAlert("info","test","Ok");
}
In your Layout background code, you can use it following code.
public partial class MainPage : ContentPage
{
PersonsViewModel personsViewModel;
public MainPage()
{
InitializeComponent();
personsViewModel = new PersonsViewModel(this);
this.BindingContext = personsViewModel;
}
If you can use plugin, you can use ACR.UserDialogs. https://github.com/aritchie/userdialogs
I solved this problem using events
public MainPageVewModel()
{
Application.Current.MainPage.Loaded += LoadCards;
}
private async void LoadCards(object sender, EventArgs e)
{
// your code on View Loaded
await Application.Current.MainPage.DisplayAlert("working alert", "alert", "ok");
}

access WebControls markable properties in constructor asp net

Here is my custom control.It inherits [Height] property from WebControl class.I want to access it in constructor for calculating other properties.But its value is always 0.Any idea?
public class MyControl : WebControl, IScriptControl
{
public MyControl()
{
AnotherProperty = Calculate(Height);
.......
}
my aspx
<hp:MyControl Height = "31px" .... />
Markup values are not available in your control's constructor but they are available from within your control's OnInit event.
protected override void OnInit(EventArgs e)
{
// has value even before the base OnInit() method in called
var height = base.Height;
base.OnInit(e);
}
As #andleer said markup has not been read yet in control's constructor, therefore any property values that are specified in markup are not available in constructor. Calculate another property on demand when it is about to be used and make sure that you not use before OnInit:
private int fAnotherPropertyCalculated = false;
private int fAnotherProperty;
public int AnotherProperty
{
get
{
if (!fAnotherPropertyCalculated)
{
fAnotherProperty = Calculate(Height);
fAnotherPropertyCalculated = true;
}
return fAnotherProperty;
}
}

Structuring a MonoTouch.Dialog application

From the examples at Xamarin.com you can build basic M.T. Dialog apps, but how do you build a real life application?
Do you:
1) Create a single DialogViewController and tree every view/RootElement from there or,
2) Create a DialogViewController for every view and use the UINavigationController and push it on as needed?
Depending on your answer, the better response is how? I've built the example task app, so I understand adding elements to a table, click it to go to the 'next' view for editing, but how to click for non-editing? How to click a button, go next view if answer is number 1?
Revised:
There is probably no one right answer, but what I've come up with seems to work for us. Number 2 from above is what was chosen, below is an example of the code as it currently exists. What we did was create a navigation controller in AppDelegate and give access to it throughout the whole application like this:
public partial class AppDelegate : UIApplicationDelegate
{
public UIWindow window { get; private set; }
//< There's a Window property/field which we chose not to bother with
public static AppDelegate Current { get; private set; }
public UINavigationController NavController { get; private set; }
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
Current = this;
window = new UIWindow (UIScreen.MainScreen.Bounds);
NavController = new UINavigationController();
// See About Controller below
DialogViewController about = new AboutController();
NavController.PushViewController(about, true);
window.RootViewController = NavController;
window.MakeKeyAndVisible ();
return true;
}
}
Then every Dialog has a structure like this:
public class AboutController : DialogViewController
{
public delegate void D(AboutController dvc);
public event D ViewLoaded = delegate { };
static About about;
public AboutController()
: base(about = new About())
{
Autorotate = true;
about.SetDialogViewController(this);
}
public override void LoadView()
{
base.LoadView();
ViewLoaded(this);
}
}
public class About : RootElement
{
static AboutModel about = AboutVM.About;
public About()
: base(about.Title)
{
string[] message = about.Text.Split(...);
Add(new Section(){
new AboutMessage(message[0]),
new About_Image(about),
new AboutMessage(message[1]),
});
}
internal void SetDialogViewController(AboutController dvc)
{
var next = new UIBarButtonItem(UIBarButtonSystemItem.Play);
dvc.NavigationItem.RightBarButtonItem = next;
dvc.ViewLoaded += new AboutController.D(dvc_ViewLoaded);
next.Clicked += new System.EventHandler(next_Clicked);
}
void next_Clicked(object sender, System.EventArgs e)
{
// Load next controller
AppDelegate.Current.NavController.PushViewController(new IssuesController(), true);
}
void dvc_ViewLoaded(AboutController dvc)
{
// Swipe location: https://gist.github.com/2884348
dvc.View.Swipe(UISwipeGestureRecognizerDirection.Left).Event +=
delegate { next_Clicked(null, null); };
}
}
Create a sub-class of elements as needed:
public class About_Image : Element, IElementSizing
{
static NSString skey = new NSString("About_Image");
AboutModel about;
UIImage image;
public About_Image(AboutModel about)
: base(string.Empty)
{
this.about = about;
FileInfo imageFile = App.LibraryFile(about.Image ?? "filler.png");
if (imageFile.Exists)
{
float size = 240;
image = UIImage.FromFile(imageFile.FullName);
var resizer = new ImageResizer(image);
resizer.Resize(size, size);
image = resizer.ModifiedImage;
}
}
public override UITableViewCell GetCell(UITableView tv)
{
var cell = tv.DequeueReusableCell(skey);
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, skey)
{
SelectionStyle = UITableViewCellSelectionStyle.None,
Accessory = UITableViewCellAccessory.None,
};
}
if (null != image)
{
cell.ImageView.ContentMode = UIViewContentMode.Center;
cell.ImageView.Image = image;
}
return cell;
}
public float GetHeight(UITableView tableView, NSIndexPath indexPath)
{
float height = 100;
if (null != image)
height = image.Size.Height;
return height;
}
public override void Selected(DialogViewController dvc, UITableView tableView, NSIndexPath indexPath)
{
//base.Selected(dvc, tableView, path);
tableView.DeselectRow(indexPath, true);
}
}
#miquel
The current idea of a workflow is an app that starts with a jpg of the Default.png that fades into the first view, with a flow control button(s) that would move to the main app. This view, which I had working previous to M.T.D. (MonoTouch.Dialog), which is a table of text rows with an image. When each row is clicked, it moves to another view that has the row/text in more detail.
The app also supports in-app-purchasing, so if the client wishes to purchase more of the product, then switch to another view to transact the purchase(s). This part was the main reason for switching to M.T.D., as I thought M.T.D. would be perfect for it.
Lastly there would be a settings view to re-enable purchases, etc.
PS How does one know when the app is un-minimized? We would like to show the fade in image again.
I have been asking myself the same questions. I've used the Funq Dependency Injection framework and I create a new DialogViewController for each view. It's effectively the same approach I've used previously developing ASP.NET MVC applications and means I can keep the controller logic nicely separated. I subclass DialogViewController for each view which allows me to pass in to the controller any application data required for that particular controller. I'm not sure if this is the recommended approach but so far it's working for me.
I too have looked at the TweetStation application and I find it a useful reference but the associated documentation specifically says that it isn't trying to be an example of how to structure a MonoTouch application.
I use option 2 that you stated as well, it works pretty nicely as you're able to edit the toolbar options on a per-root-view basis and such.
Option 2 is more feasible, as it also gives you more control on each DialogViewController. It can also helps if you want to conditionally load the view.

Add ability to provide list items to composite control with DropDownLIst

I'm creating a composite control for a DropDownList (that also includes a Label).
The idea being that I can use my control like a dropdown list, but also have it toss a Label onto the page in front of the DDL.
I have this working perfectly for TextBoxes, but am struggling with the DDL because of the Collection (or Datasource) component to populate the DDL.
Basically I want to be able to do something like this:
<ecc:MyDropDownList ID="AnimalType" runat="server" LabelText="this is what will be in the label">
<asp:ListItem Text="dog" Value="dog" />
<asp:ListItem Text="cat" Value="cat" />
</ecc:MyDropDownList>
The problem is, I'm not extending the DropDownList class for my control, so I can't simply work it with that magic. I need some pointers to figure out how I can turn my control (MyDropDownList), which is currently just a System.Web.UI.UserControl, into something that will accept List items within the tag and ideally, I'd like to be able to plug it into a datasource (the same functions that the regular DDL offers).
I tried with no luck just extending the regular DDL, but couldn't get the Label component to fly with it.
After doing some digging and searching I found a solution that works. Hopefully this will help someone else out in the future:
[ParseChildren(true, "Items")]
public class EDropDownList : CompositeControl, IValidatedFields
{
public string PromptingText { get; set; }
public string Value { get; set; }
public Label __Label { get; set; }
private ListItemCollection _items;
public DropDownList __DropDownList;
public ListItemCollection Items
{
get { return _items; }
set
{
if (_items != value)
{
_items = value;
}
}
}
public string Type { get { return "DropDownList"; } }
public EDropDownList()
{
__Label = new Label();
}
protected override void CreateChildControls()
{
__DropDownList = new DropDownList();
foreach (ListItem myItem in _items)
{
__DropDownList.Items.Add(myItem);
}
Controls.AddAt(0, __Label);
Controls.AddAt(1, __DropDownList);
}
protected override void OnLoad(EventArgs e)
{
// label section
__Label.Text = PromptingText+"<br />";
__Label.ForeColor = Color.Red;
__Label.Visible = false;
// ddl section
if (Page.IsPostBack)
Value = __DropDownList.SelectedValue;
}
}
The easiest thing would be to go back to your original option of extending the DropDownList control. What problems did you have getting the label to work with it? Those problems are probably easier to solve?

Resources