Here is an example:
<Grid x:Name="LayoutRoot">
<Control Value="{Binding Parent.Margins.Top, ElementName=LayoutRoot}"/>
</Grid>
I want to get type of the "Top" property to set correct value (null if it's nullable or "empty" parameter). How can I do this?
If you write an IValueConverter, and use that as the Converter for the Binding expression, then inside of the Convert/ConvertBack methods, you should get the value (typed as "object") and you can use GetType() on that to inspect it and decide how you want to act.
Related
I set up multiple different views that I can inflate from xaml like so:
<Grid Grid.Row="2" x:Name="grid_someelsesprofile_currentproducts">
<!-- ID = 4 for profile-->
<views:CV_AllAdsRes>
<x:Arguments >
<x:Int32>4</x:Int32>
</x:Arguments>
</views:CV_AllAdsRes>
</Grid>
I even pass a parameter, in this case an int with the value of 4.
Now I need to be able to inflate this also but from code and also pass the parameter and add this view to the grid. So basically all I am doing from above only from code basis.
CV_AllAdsRes is a contentview file.
How would that translate?
Thank you :)
It is actually super easy:
load the class holding the view and logic:
var xy = new CV_AllAdsRes(4, userID);
Then add class to grid.children method:
grid_someelsesprofile_currentproducts.Children.Add(xy);
I got a page in which I load multiple control template considering some business logic binded to a property in my viewModel.
<ContentView x:Name="ContentView" ControlTemplate="{Binding ItemControlTemplate}">
</ContentView>
Inside this control template I got a CarouselViewControl which uses a DataTemplate.
<carousel:CarouselViewControl x:Name="CarouselViewMapTemplate" Position="
{TemplateBinding BindingContext.CarouselPosition}"
PositionSelectedCommand="{TemplateBinding BindingContext.PositionChanged}"
Orientation="Horizontal" AnimateTransition="True" IsSwipeEnabled="False"
ItemsSource="{TemplateBinding BindingContext.Items}" InterPageSpacing="10"
ItemTemplate="{StaticResource ItemsDataTemplate }">
</carousel:CarouselViewControl>
And inside this DataTemplate I would like to bind to a property in the ViewModel, which is also a DataTemplate.
<maps:SfMaps x:Name="sfmap" EnablePanning="False" EnableZooming="False" BackgroundColor="Transparent">
<maps:SfMaps.Layers>
<maps:ShapeFileLayer x:Name="ShapeLayer" Uri="FRA_adm0.shp" MarkerTemplate="{Binding Parent.BindingContext.MarkerDataTemplate}">
</maps:ShapeFileLayer>
</maps:SfMaps.Layers>
</maps:SfMaps>
How can I achieve that ? I just tried
{Binding Parent.BindingContext.MyProperty}
but this is not working. I also digged with Source property of binding, but that won't do it as I don't have reference in my DataTemplate, used as resource in the app level ResourceDictionary.
This DOESNT work ofc it does not find carouselView in the ResourceDictionary :
"{Binding Path=BindingContext.DisplayMarkerTemplateCommand, Source={x:Reference carouselView}}"
Not being able to do that breaks the whole point of having ResourceDictionary and clean templating if binding is not working from it with XAML.
THANKS !
I'm trying to create a XAML UI based on the condition.
<StackLayout Orientation="Horizontal">
<!--IF WorkEmailAddress != NULL && WorkEmailAddrress != ""-->
<!-- BEGIN IF -->
<Label Text="{Binding WorkEmailAddress}" Style="{StaticResource labelListItem}"></Label>
<Image HeightRequest="16" HorizontalOptions="End" VerticalOptions="Center" Source="arrow.png" Margin="0,0,15,0"></Image>
<!-- END IF -->
<!-- ELSE -->
<Label Text="Add new email" Style="{StaticResource labelLinkItem}">
</StackLayout>
Could one please let me know how to add a IF ELSE condition with in the XAML to dynamically create a UI based on the value returned from the backend.
You can't do this completely in XAML. Probably the best way to go is to add a bool property to your view model named HasWorkEmailAddress (I'm assuming you have one, and that's where WorkEmailAddress lives) which returns true if there's a non-null, non-empty value for WorkEmailAddress.
You can then bind the first label and Image's IsVisible property to this bool.
You can also create an InverseBooleanConverter, which will implement IValueConverter. The Convert method will simply take a bool and negate it, and return that value. Bind your second labels' IsVisible to the same bool, but specify the InverseBooleanConverter as the binding's Converter. It will then show only if the HasWorkEmailAddress returns false. The labels binding will look like this:
<Label IsVisible="{Binding HasWorkEmailAddress, Converter={StaticResource InverseBooleanConverter}}" />
If you don't want to write your own converter, one exists in the FreshEssentials Nuget package.
One last thing; if its possible for WorkEmailAddress to change while the page is being shown, you'll need to make sure you raise a PropertyChanged event for the HasWorkEmailAddress property, or your view will not change appropriately.
I have an "AddressListBox" ListBox that contains "AddressDetails" UserControl items, as shown in the .xaml file extract below. The Addresses collection is defined as
ObservableCollection< Address > Addresses
and Street, Number, PostCode, City are properties of the Address class. The binding fails, when I use the "{Binding property}" syntax shown below. The binding succeeds, when I use the "dummy" strings in the commented-out code. I have also tried "{Binding Path=property}" syntax without success. Can you suggest what syntax I should use for binding the data in the user controls?
<ListBox x:Name="AddressListBox"
DataContext="{StaticResource dataSettings}" ItemsSource="{Binding Path=Addresses, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--
<usercontrols:AddressDetails AddressRoad="dummy" AddressNumber="dummy2" AddressPostCode="dummy3" AddressCity="dummy4">
</usercontrols:AddressDetails>
-->
<usercontrols:AddressDetails AddressRoad="{Binding Street}" AddressNumber="{Binding Number}" AddressPostCode="{Binding PostCode}" AddressCity="{Binding City}">
</usercontrols:AddressDetails>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You need to set the datacontext on the usercontrol to the item like this.
<usercontrols:AddressDetails DataContext={Binding}
...
</usercontrols:AddressDetails>
Now your other bindings should work correctly as they are relative to the item.
I'm a bit of a .net newbie and I've been working on my first big silverlight project. So pardon the lack of lingo and the length of the question. But my problem is as follows.
The project is being built according to the MVVM pattern ( in this case I'm using LightMVVM ). Most of the views contain ListBoxes. These listboxes need to handle multiple different types of data each of which has it's own visual look. After some poking around I decoded tp try this implementation for datatemplate selection:
http://silverscratch.blogspot.com/2010/04/changing-data-templates-at-run-time.html
Some of my items, however, have sub controls that need to talk to the viewmodel. From what I've been reading Commands with element bindings is the best ways to handle this.
So, for example:
<Grid x:Name="NavMainLayoutRoot" DataContext="{Binding Source={StaticResource NavMainViewModelDataSource}}" Margin="15,0,0,0">
....
<ListBox x:Name="MenuListBox" HorizontalAlignment="Left" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource MainNavigationButtonStyle}" Padding="0" VerticalAlignment="Top" >
<ListBox.RenderTransform>
<CompositeTransform/>
</ListBox.RenderTransform>
<ListBox.ItemTemplate>
<DataTemplate>
<xxxControls:SelectableContentControl TemplateName="{Binding Path=Type}" Content="{Binding Details}" IsTabStop="{Binding IsHitTestEnabled}">
<xxxControls:SelectableContentControl.Templates>
<DataTemplate>
<local:GenericItem />
</DataTemplate>
<DataTemplate x:Name="navbutton">
<local:MainNavItem />
</DataTemplate>
</xxxControls:SelectableContentControl.Templates>
</xxxControls:SelectableContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
....
And MainNavItem, simplified is:
<Grid x:Name="NavItemRoot" VerticalAlignment="Top" Margin="0,0,0,0">
<Button Content="{Binding Label}" VerticalAlignment="Top" Style="{StaticResource MainNavItemButtonStyle}" HorizontalAlignment="Left" Margin="5,0" Command="{Binding DataContext.NavButtonClick, ElementName=NavMainLayoutRoot}"/>
</Grid>
The problem is that this didn't work. So for grins I went ahead and copy and pasted the code for the MainNavItem directly into the tag and like magic it started working.
Since I reuse a lot of these item templates all over the application, having them in nice contained external files is very nice and not something I want to give up.
(( Thinking about it, this example is not the best, suffice it to say that some of these data templates contain multiple controls and I can't just use selectedItem on the listbox to handle the selected events. ))
So any suggestions are welcome. What's the best practice here?
My first thought is that something in your MainNavItem user control is setting its DataContext to something else. If you don't set the DataContext it should automatically pick it up from the current item in your MenuListBox.
You can try creating a test value converter and putting a breakpoint in it to check what the data context is at runtime.
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value; // put break point here to test data binding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value;
}
}
And modify your MainNavItem to look like this in order to break in the TestConverter at runtime.
<UserControl.Resources>
<ResourceDictionary>
<TestConverter x:Key="TestConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="NavItemRoot" DataContext="{Binding Converter={StaticResource TestConverter}}">
<Button Content="{Binding Path=Label, Converter={StaticResource TestConverter}}" />
</Grid>
This will help you determine the issue with data binding.
I suspect that the problem with your command is that you're using element-to-element data binding to attempt to bind to an element that is outside of the user control you're currently within. This won't work. Instead, try setting up your NavMainViewModelDataSource static resource in App.xaml, then you can bind directly to it from your user control.
<Button Content="{Binding Label}" Command="{Binding Path=NavButtonClick, Source={StaticResource NavMainViewModelDataSource}}" />