Set view element BindingContext - mvvm cross - mvvmcross

Is it possible to set element data context in MvvmCross?
Suppose I have:
<RelativeLayout>
<TextView/> <TextView/>
</RelativeLayout>
and I'd like to set RelativeLayout data context to viewmodel property.
XAML equivalent of:
<Grid DataContext="{Binding someProperty}">
<TextBlock/> <TextBlock/>
</Grid>

You can't currently do this directly in a single axml file in MvvmCross at present.
However:
You can use MvxFrameControl to load a sub-axml file (a bit like an include) and then set the DataContext for everything inside that sub-view
MvvmCross is open source - so you can extend and adapt it...

Related

Flex 4.6 setting selectedChild= with a bound Variable from a Component

I'm getting the following error:
1067: Implicit coercion of a value of type String to an unrelated type mx.core:INavigatorContent.
Which is located in my main application at the line where I set the selectedChild=
Here's my code for my viewstack which is in my main application:
<mx:ViewStack id="mainViewStack"
width="100%" height="100%"
selectedChild="{topViewControlComponent.selectedChild}">
My component contains the following:
[Bindable]
public var selectedChild:String;
protected function changeView2(child:String):void
{
this.selectedChild = child;
}
<s:Button styleName="controlBarButton"
label="Events"
click="changeView2('userEvents');"/>
I got this to work when I set the viewstack navigator content base off of selectIndex and using an integer...worked fine. But I would rather call them by the id of the Navigator content so that they don't have to be in specific order, if this is possible. Or maybe there's a better way to go about this...Thanks for any help!
The selectedChild property on the ViewStack takes an actual view as its argument, not the name of a view. Using selectedIndex with an int will work fine, or you could call a function in your main application that maps between id and view instance.
Edit: As you said in the comments, you can use click="mainViewStack.selectedChild=userEvents" to set the view as desired.
However, your code in the question is acting like this:
click="mainViewStack.selectedChild='userEvents'"

Customize sparrow toolkit axis label

I like customize axis label style in sparrow toolkit. i wrate this code:
<sparrow:SparrowChart.XAxis>
<sparrow:CategoryXAxis Interval="1">
<sparrow:CategoryXAxis.LabelTemplate>
<DataTemplate>
<TextBlock Text="V" FontSize="12"/>
</DataTemplate>
</sparrow:CategoryXAxis.LabelTemplate>
</sparrow:CategoryXAxis>
</sparrow:SparrowChart.XAxis>
i like replace static string "V" with X property value of Model object that i use to build the collection of points. i don't understand how to set DataSource and how to build it.
if i don't define DataTemplate, at run time i have the right X value, but i need change the color.
I hope someone can help me.
Have you set the SparryChart's DataContext and bind your DataSource to it?
Maybe you can read the code here:Column Chart
You can set Text={Binding XProperty}. XProperty is your binding property of your model. Have declare a property in your model? Then set your model as DataContext to your Chart control.

Binding to Windows::UI::Xaml::GridLength in C++/CX

I am trying to bind to a GridLength instance in a Windows Store app (compiled with the Visual Studio 2013 compiler) in C++/CX, but for some reason I keep getting the following error at runtime:
Error: Converter failed to convert value of type 'Windows.Foundation.IReference`1<Windows.UI.Xaml.GridLength>' to type 'GridLength'; BindingExpression: Path='MyHeight' DataItem='MyNamespace.MyObject'; target element is 'Windows.UI.Xaml.Controls.RowDefinition' (Name='null'); target property is 'Height' (type 'GridLength').
My code essentially looks like:
namespace MyNamespace
{
[Windows::UI::Xaml::Data::Bindable]
public ref class MyObject sealed
{
property Windows::UI::Xaml::GridLength MyHeight
{
Windows::UI::Xaml::GridLength get() { return myHeight; }
}
}
}
and my XAML file essentially looks like:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding MyHeight}"/>
</Grid.RowDefinitions>
</Grid>
Just FYI, other properties in my class are binding properly. The issue appears to only be with the GridLength value struct. It is obviously finding the property correctly, but for some reason it can't match up the types.
A RowDefinition is not a FrameworkElement, so it doesn't have a DataContext. Binding won't work here. You can put a Rectangle in that row though, set the row height to Auto and bind the Rectangle.Height to a property you want. That could work for some scenarios. For others there might be better solutions, but you would need to specify what exactly you are trying to achieve.
So, it appears that the property type projection isn't working as you or I would expect it to. It's wrapping the GridLength property in an IReference<T> (or, in C#, Nullable<T>). Try binding to MyHeight.Value.

Force GridView To Create Not Recycle Controls

I have a GridView in a windows store app that has an ItemContainerStyleSelector. Within the style is an Image control that has a custom dependency property to set the source (This is so I can get a handle on the Image and hook up to the unloaded event).
My issue is the Image is never unloaded and seems to be reused. This means that when I set the source, the image is set on other items in the GridView as well (For Example I have an object which has no image but after scrolling away and then back again it has an image from another object).
I've tried to set virtualization mode to standard where I can but it doesn't help. Any ideas would be greatly appreciated.
Here is the Image that is contained in the style. This is passed to a method "OnRemoteURISourceChanged" when set. I'd expect a different image control whenever the method is called but this is not the case.
<Image x:Name="BackgroundImage" DataContext="{Binding CurrentBackdrop}" helpers:ImageExtensions.RemoteURISource="{Binding Uri}" Stretch="UniformToFill"/>
And here is my GridView
<GridView x:Name="ItemsGrid" Grid.Row="1" ItemsSource="{Binding BrowseResults}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Margin="20,0,20,0"
IsItemClickEnabled="True" ItemClick="ItemsGrid_ItemClick" VirtualizingStackPanel.VirtualizationMode="Standard">
<GridView.ItemContainerStyleSelector>
<controls:UPnPCDStyleSelector CDObject="{StaticResource somestyle1}" Container="{StaticResource somestyle2}" Item="{StaticResource somestyle3}"/>
</GridView.ItemContainerStyleSelector>
<GridView.ItemsPanel>
<ItemsPanelTemplate VirtualizingStackPanel.VirtualizationMode="Standard">
<WrapGrid Orientation="Vertical" VirtualizingStackPanel.VirtualizationMode="Standard"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
UPDATE: The issue appears to be the WrapGrid. If I change this to a VirtualizingStack Panel and set the VirtualizationMode to Standard then everything works as expected but obviously my items then only appear on one line and not multiple lines as I wish.
How do I set the virtualization mode of a WrapGrid?
Is there a chance your helpers:ImageExtensions.RemoteURISource doesn't clear the Image.Source when either your CurrentBackdrop property or its Uri property value is null?
Are you sure the task which is loading the img source returns to default ui context when awaiting? I don't think it is a good idea to set Image.Source property form code. The better solution would be to create a custom observable task class and bind im source to it's result. In the background you can call the task. Do you need the control to be Image? Because if it would be a control with template, it would be easier for you to do that. I can send you the class which does that if you want to.

Accessing named controls from page resources

I needed to access to the ActualWidth of a Border that didn't have a specified Width. I have been told that I can't do that on WinRT so I used a proxy from Florian-Gl (from here).
The thing is that I need to create that proxy on the page's resource like this:
<Page.Resources>
<utils:ActualSizePropertyProxy Element="{Binding ElementName=noteBorder}" x:Name="proxy" />
</Page.Resources>
The problem is that I don't have access to that noteBorder element from the resources, but I have access to pageRoot that is the Page itself.
I guess that I can play with ElementName / Path to get access to noteBorder.
But there is some curious stuff:
The structure is something like:
Page (pageRoot) > Grid > ListView > ListView.ItemTemplate > Grid > Border (noteBorder)
So, If I create the proxy at the same level of the border, It won't run but If I change the ListView to a ItemsControl, it will run and works as expected.
If having it at the same level of the border I change the ElementName to pageRoot it will run at least.
So, It won't run if I put noteBorder (even when I have access to it) if I'm using a ListView, but will work on a ItemsControl, On the other hand, If I have pageRoot it works all ways.
So the question is: Is there a way to access noteBorder from resources? Or maybe a way to access it from another place but working :P
You should be using an Item Template --
By the time you get to
pageRoot) > Grid > ListView or Items Control
At this point in the structure, you're at the element you really want to get at, which is the container of the items that will need the border you are trying to access.
You should define an Item Template and assign the ListView's (or ItemsControl's) ItemTemplate property via binding.
<ListView x:Name="myListView" DataContext="{Binding ToElementIfNotInheritedFromParent}" ItemsSource="{Binding ViewModelListBeingBoundTo}" ItemTemplate="{Binding Source={Static Resource MyCustomItemTemplate}}" />
Where MyCustomItemTemplate is something like
<DataTemplate x:Name="MyCustomItemTemplate">
<Border x:Name="myBorder" >
<StackPanel>
<TextBlock Text="{Binding Path=Title}" />
<TextBlock Text="{Binding Path=FirstProperty}"/>
<TextBlock Text="{Binding Path=SecondProperty}"/>
</StackPanel>
</Border>
</DataTemplate>
Then In your Codebehind (or if ViewModel use the code behind to pass the ListView object to the ViewModel)
DataTemplate dt = this.myListView.Items[indexOfChoice].ItemTemplate as DataTemplate;
Border b = dt.LoadContent() as Border;
int actualWidth = b.AcutalWidth
OR
You can create a FindControl() method that runs recursively to extract the actual control within the border, for instance if you wanted to access one of the Textboxes.
The code for that is here:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/a612f5a6-e05e-4b68-a813-893eeda159cc