Binding to Global variable in Silverlight for WP7 - windows-phone-7

Let's say that I have a global variable defined in App.xaml.cs as follows:
public static MyClass GlobalInstance = new MyClass()
And then in MainPage.xaml I would like to bind to a property of this class like follows:
<TextBlock Text="{Binding App.GlobalInstance.Property1}" VerticalAlignment="Top" Height="31" HorizontalAlignment="Left" Width="80">
Is there something I am missing here? For some reason it does not appear to be properly bound.
Any advice here would be greatly appreciated.
Thanks!

You need to assign your App to DataContext of the page
First way is do this in page constructor:
public MainPage()
{
InitializeComponent();
DataContext = App.Current;
}
And your binding will be
{Binding GlobalInstance.Property1}
The second way is to make a reference to App class in page resources
Also, edit your field implementation to something like this:
public static MyClass GlobalInstance {get; private set; }
...
GlobalInstance = new MyClass();

Related

Xamarin access to entry in other view

I'm developing Multiplatform app through Xamarin.
I'm using custom entry in a separate view and I'm using in some pages of my app
This is my simple code for entry
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="prova.MyView">
<ContentView.Content>
<Entry x:Name="MyEntry"
TextChanged="MyEntry_TextChanged"
Margin="100"/>
</ContentView.Content>
and cs file
public partial class MyView : ContentView
{
public MyView()
{
InitializeComponent();
}
void MyEntry_TextChanged(System.Object sender, Xamarin.Forms.TextChangedEventArgs e)
{
}
}
in my pages I insert entry with this simple code
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="prova.MainPage"
xmlns:pages="clr-namespace:prova">
<StackLayout>
<pages:MyView/>
</StackLayout>
I wonder how can I get when MyEntry_TextChanged is fired in my ContentPage?
one solution is to use MessaggingCenter but I wonder if there's a better and more elegant solution
There are two ways I can think of to do this.
1. Inherit from the Entry class as Jason commented.
public class MyView : Entry
{
public MyView()
{
InitializeComponent();
}
}
This will expose the bindable TextChanged property which you can reference in XAML like you want to do.
2. Create the binding yourself
You can create the binding to a custom "TextChanged" property yourself, but this is more complicated and may achieve the same result with extra effort. You will also need to create a bindable "Text" property. The code below is untested, but uses the bindings I found in the Xamarin.Forms InputView class (which is what Entry derives from). This will be along the lines of what you need to do if you do not do it the way of #1. Exposing bindable properties to XAML will look like this:
public class MyView : ContentView
{
public MyView()
{
InitializeComponent();
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(MyView), defaultValue: "", propertyChanged:
(bindable, oldValue, newValue) => ((MyView)bindable).OnTextChanged((string)oldValue, (string)newValue));
public event EventHandler<TextChangedEventArgs> TextChanged;
protected virtual void OnTextChanged(string oldValue, string newValue)
{
TextChanged?.Invoke(this, new TextChangedEventArgs(oldValue, newValue));
}
}
I hope my more comprehensive answer helps you choose the direction you want to go for this. If you want to learn more about Bindable Properties, check out Edward's link.

If I use ContentPage.BindingContext in XAML to define my binding context then how do I access that in the C# back end?

In my XAML I define the binding context like this:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Japanese;assembly=Japanese"
             xmlns:template="clr-namespace:Japanese.Templates"
             xmlns:viewModels="clr-namespace:Japanese.ViewModels; assembly=Japanese"
             x:Class="Japanese.Cards" Title="{Binding Title}">
<ContentPage.BindingContext>
     <viewModels:CardsViewModel />
    </ContentPage.BindingContext>
</ContentPage>
What I would like to know is how can I access this context in my C# back end.
public partial class Cards : ContentPage
{
public Cards()
    {
     InitializeComponent();
        NavigationPage.SetBackButtonTitle(this, "Back");
    }
    protected override void OnAppearing()
    {
     // I want to set some properties of the view here
It seems you cannot give it an x:Name attribute like other elements in your XAML. In that case, your options are limited to declaring the object for your binding context in the code-behind, or referencing it from the BindingContext property.
For the latter approach, do it like this:
protected override void OnAppearing()
{
var cardsViewModel = BindingContext as CardsViewModel;
if (cardsViewModel == null)
return;
cardsViewModel.Property = Value;
}
Earlier answer for reference:
You should be able to give it a name like so:
<ContentPage.BindingContext>
<viewModels:CardsViewModel x:Name="cardsViewModel" />
</ContentPage.BindingContext>
This will effectively just create a declaration like this in generated code:
private CardsViewModel cardsViewModel;
You can now access it in your code-behind:
protected override void OnAppearing()
{
cardsViewModel.Property = Value;
}

My databinding fails, is the path wrong?

I'm trying to create a simple RSS news aggregator. But I've done something wrong with the binding.
The xaml:
<phone:LongListSelector
x:Name="MainLongListSelector"
Margin="0,0,-12,0"
ItemsSource="{Binding Path=News.List}"
SelectionChanged="MainLongListSelector_SelectionChanged">
The code behind:
(mainpage)
public MainPage()
{
InitializeComponent();
// Set the data context of the LongListSelector control
// to the sample data
DataContext = App.ViewModel;
(viewmodel)
public class NewsViewModel : BaseViewModel
{
public NewsRepository News { get; private set; }
}
The NewsRepository is just an model object holding the List<obj> List. Could anyone point me in the direction where thing goes sideways?
The app runs just fine but the single item in the List I've put in manually does not show up in the application :-(
I've set and breakpoint at the assignment of the DataContext to the the viewmodels content its there...
Both NewsViewModel and NewsRepository have to implement INotifyPropertyChanged.
It would be easier if you use ObservableCollection<obj> as a source of your binding instead of custom NewsRepository object.

How to change a property of ViewModel property and make the change reflects on the bound control?

I'm writing a windows Phone app; and as a good citizen I'm using MVVM pattern :) Being not so expert in MVVM, I faced the following issue that I hope I find solution for here.
I have the following code:
XAML
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding MyPOCO}">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding IsActive}"/>
</StackPanel>
</Grid>
Code Behind
this.DataContext = new ViewModel();
ViewModel
public class ViewModel : ViewModelBase
{
private POCO myPOCO;
public ViewModel()
{
this.myPOCO = new POCO();
this.ToggleActiveStatusCommand = new RelayCommand(this.ToggleActiveStatus);
}
public POCO MyPOCO
{
get
{
return this.myPOCO;
}
}
public RelayCommand ToggleActiveStatusCommand { get; private set; }
private void ToggleActiveStatus()
{
this.MyPOCO.IsActive = !this.MyPOCO.IsActive;
System.Diagnostics.Debug.WriteLine(this.MyPOCO.IsActive);
this.RaisePropertyChanged("MyPOCO");
}
}
POCO
public class POCO
{
public string Name { get; set; }
public bool IsActive { get; set; }
}
What I'm trying to achieve is to change the TextBlock text as the value of IsActive changes... how to do that? I mean other than exposing the required properties from POCO as properties to ViewModel.
Thanks
I think you will have to implement properties in your ViewModel that call into the POCO properties unless you implement INotifyPropertyChanged in your POCO which then goes against MVVM where your Model should just hold your data and your ViewModel is the glue that links the Model with the View.
Creating properties in your ViewModel may seem like alot of additional work but it does add the benefit of being able to define many ViewModels based on a single Model. So in the specific ViewModel you only expose properties that you need rather than everything the Model can offer you.
Once you have defined your ViewModel properties, you may need to set the Mode of your Binding to TwoWay so that the UI can be updated when the underlying ViewModel properties change.

Why does the data binding source need an explicit getter?

If I don't add explicit accessors to a String property, then data binding doesn't work. Why is that?
Here is a simple example where a text box is hooked up to a String property.
MainPage.xaml:
<Grid Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Text="{Binding Message} />
</Grid>
And the code behind:
public String Message;
public MainPage()
{
InitializeComponent();
Message = "Hello World";
DataContext = this;
}
This does not work, the text box is empty.
However, add property accessors;
public String Message { get; set; };
And now it works.
I can't see this explained in MSDN Data Binding. Can someone explain it? Don't properties have an implict set/get accessors? Even so, why can't data binding just access the property?
Thanks,
public String Message;
This is a field, not a property. Adding getters and setters creates an auto property.
Only properties can be bound to.
The { get; set; } is what makes the compiler generate those implicit accessors. If you leave that out, you're not creating a property at all, but a simple field.
I'm not into XAML that much so I can't say for sure, but maybe it just doesn't support binding to plain fields.
public String Message; is a field, not a property.
Databinding only works with properties.

Resources