How to alter a DataTemplate based on a property on the page ViewModel in Windows Phone 7? - windows-phone-7

I have a ViewModel which contains a Boolean property which tells you if the user has authenticated or not.
I have a WrapPanel which is bound to a collection of profiles. The DataTemplate for these profiles has an icon - a closed padlock for when the user is not authenticated and an open one for when the user is authenticated. Ideally these would be bound to the Boolean on the ViewModel but the DataContext for the templates is the individual profile objects.
I have tried,
Setting the Source selector in the binding as specified here although it appear Windows Phone 7 does not support x:Reference
I tried also the Inversion of Control(?) method detailed here (but containerLocator was not found on my object)
I tried applying a Style.Trigger but these are not supported in Windows Phone 7
I also tried accessing the XAML elements in the code behind and updating programmatically on event triggers, however I could not get a handle on the Image element inside the DataTemplate

Edit after comment: WP7 does not support style triggers. But if anyone is looking for this answer on following versions I let the reply below:
I would use a Style Trigger as seen here to update the icon Source property on the fly - as part of the style of your DataTemplate so you would get a hold of your Image.

One way I found that works based on an answer by Damian Antonowicz but does not implement the full inversion of control method that he uses, is as follows,
Create a partial class which resolves to your view-model instance under your view-model namespace, e.g.
public partial class ViewModelInstanceLocator
{
public AppViewModel AppViewModel // Or whatever the type of your view-model is ...
{
get
{
return App.VM; // Or wherever your view model instance is ...
}
}
}
Define the other half of the class in your XAML page as a resource so that it can be referred to as a static resource, I did this in my App.xaml so that it could be referred to everywhere,
<ResourceDictionary>
<viewmodel:ViewModelInstanceLocator x:Key="ViewModelInstanceLocator" />
...
</ResourceDictionary>
You may need to include the relevant namespace if there is not already a reference to your view-model namespace e.g. at the top,
xmlns:viewmodel="clr-namespace:MyAppNamespace.ViewModel"
Finally to bind to the view-model as follows,
{Binding AppViewModel.SomeProperty, Source={StaticResource ViewModelInstanceLocator}}
The binding updates as usual just as if the view-model instance had been referred to through the DataContext. However, it does not work with design-time data.

Related

How can I add to my page layout with code in the ViewModel?

My page layout looks like this:
<StackLayout x:Name="detailsLayout" VerticalOptions="FillAndExpand">
</StackLayout>
When I create my ViewModel I pass in a pointer to the page. What I would like to do is this:
public class CardsViewModel : BaseViewModel
{
private readonly Cards cardsPage;
public CardsViewModel(Cards cardsPage)
{
this.cardsPage = cardsPage;
}
async public Task CardBtn()
{
cardsPage.detailsLayout.Children.Clear();
But I don't have access to the detailsLayout due to its protection level.
Can someone tell me how I can get access to do this?
The example above is an example of coupling and breaking the separation between the ViewModel and the View(Page). If you want to benefit from MVVM pattern - don't keep a reference to your UI layer and definitely don't try to manipulate the UI layer directly in the ViewModel.
What you should do instead is depends on your needs, however I can give you few ideas:
Encapsulate the logic within the UI control it self, exposing a delegate, command or property you could bind to from your ViewModel to trigger the specific event.
Keep the logic on UI layer, the Page itself and use a MessagingCenter to communicate to it from the ViewModel.
Good luck.
P.S.: You can find more information and examples about MessagingCenter in the official Xamarin documentation. Just don't forget to unsubscribe, otherwise you will find yourself in a bad place.

Xamarin Picker selected item persisting on multiple pages

Question:
Perhaps the challenge could be stated this way: How do I bind a single property in a content page to a globally stored variable in Xamarin Forms?
Details:
I am using the MVVM pattern. I have a navigation content page (1 of 3 such pages) with a Picker object which is populated dynamically from the collectionModel and said model is read/write. I am attempting to persist the SelectedItem (or index, whichever is most appropriate) thru all 3 content pages such that navigation from page to page shows the same item (from the user's perspective). How should I do this?
I can set the Picker.SelectedIndex manually in ContentPage_Appearing() event. I would much rather use binding.
Follow these steps:
Create a static class, like this:
public static class DataClass
{
public static int PickerSelectedIndex = 0;
}
Add the xmlns:local in ContentPage mark in each Content Page, like this:
xmlns:local="clr-namespace:DataPersist"
Binding the data for your controls in each page's Xaml, like this:
<Picker x:Name="picker" SelectedIndex="{x:Static local:DataClass.PickerSelectedIndex}">
It works like this:

Panorama Control not showing data

I am making a Panorama Windows Phone 8 app. This is the first time I have actually used one in an app.
I am having problems showing the data in runtime. Instead I am only seeing a list:
RuntimeOne
RuntimeTwo
RuntimeThree
etc..
I don't have a clue what has happened, it worked the other day. I am going into the SampleData folder and changing LineOne, LineTwo, LineThree, etc but it's not doing anything when I deploy the app to the Windows Phone Emulator.
What's happening is that there are two different sets of data, and the DataContext at runtime is different from design time.
The data that you see in design mode ('design one', 'design two') is
stored in MainViewModelSampleData.cs, so changing that doesn't affect
the runtime experience.
The data at runtime is coming from the LoadData method in
MainViewModel.cs
At the top of MainPage.xaml, you'll see
d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
and the "d" namespace here is a mnemonic for 'design'. If you look at the sample data XAML file, you'll notice it declares a class called MainViewModel with a collection of Items.
At runtime, MainViewModel.cs (specifically the LoadData method) adds items one by one to the Items property of the MainViewModel class, and that class is in turn set to be the runtime DataContext in the constructor of MainPage
The panorama control itself has markup like
<phone:LongListSelector Margin="0,0,-22,0" ItemsSource="{Binding Items}">
so it's expecting to see a collection called Items on whatever the current DataContext is, and the fact two different data contexts are in play explains what you're seeing.
The data binding magic is incredibly cool and powerful, but sometimes does leave you scratching your head.

How do you access the MainViewModel in ViewModelLocator from code behind?

Building a WP7 app using MVVM light for my view models. I'm using the ViewModelLocator that gets added when you add the library through NuGet. Works great but now I need to get access to a ViewModel from code.
In my code the user clicks a button and I need to search the MainViewModel (which contains several view models) and find one based on the criteria the user entered.
Normally I would just response to the Click event of the button but I don't have an instance variable of the ViewModelLocator class to get a hold of the MainViewModel to perform the search. With the default template (non-MVVMLight) for Windows Phone 7, the App class has a static variable to the main view model so you can access it anytime with App.ViewModel.
There's some talk from twitter about using commands which would be good, but at some point I have to perform a code search across multiple vms to get the results I need. Probably need to inject a ISearchViewModel service into the View or something to make this work.
Here's the implementation of ViewModelLocator that is provided:
public class ViewModelLocator
{
private static MainViewModel _main;
public ViewModelLocator()
{
_main = new MainViewModel();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return _main;
}
}
}
So from the code behind of another view, how do you get access to Main (MainViewModel contains all the lists of data and has a search method I call)? Or Should you?
Just wondering how people are solving this type of problem?
Thanks.
In MVVM-Light the ViewModelLocator is provided as an application resource. Therefore you can still directly access it, but the syntax is different. If you look at your App.xaml you should see this piece of code somewhere.
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
</Application.Resources>
From anywhere in your application you can access the App's resources and therefore also the MainViewModel with this piece of code:
(App.Current.Resources["Locator"] as ViewModelLocator).Main
This works for any application resource.
If you created the ViewModelLocator as in the template you have static references to the ViewModels. The mvvmlocatorproperty-snippet creates ViewModel-properties like this.
This means that you could just instantiate a new ViewModelLocator to locate the ViewModels in your code behind button click. It will always be the same viewmodels independent of the different instances of the ViewModelLocator
To access the MainViewModel from your code you can add this property to your class:
public ViewModel.MainViewModel myContext { get { return (DataContext as ViewModel.MainViewModel); } }
Then you can just use myContext.[whatever]
You can just use ViewModelLocator.MainViewModelStatic. Default template for MVVMLight have a static property for each your viewmodel.

Styling an extended TextBox control in Windows Phone 7

Totally new to custom control creation in Silverlight.
I'm wanting a custom control that inherits from a TextBox control. I've found plenty of tutorials but they all do something like watermarked text or other attached properties. My goal is only to manipulate text at time of entry using the KeyUp event, so visually my TextBox is no different from a standard TextBox.
I created a class file and inherited from TextBox, but at run-time the textbox doesn't display. From what I can gather I need a themes/generic.xaml file, but all of samples I've seen include styles for the additional properties, and in my ignorance I don't know what to change and/or remove.
I'm hoping someone can point me to a generic plain-jane TextBox style definition or a tutorial of such.
What you described should work, I just tried the following and the TextBoxEx renders just fine:
public class TextBoxEx : TextBox
{
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
}
}
You do not need to add a generic.xaml file. This file is used to provide a template which defines the look of your control. You specify the default look of your control by setting the following property:
DefaultStyleKey = typeof(MyControl);
However, as the above TextBoxEx does not set this property, it uses the value inherited from TextBox and hence it inherits the same template (i.e look).

Resources