Multi binding in UWP - xaml

I want to display a textblock with latitude and longditude. In my model, the lat and lng are two variables, so I need to combine them, preferably with stringformat as this answer suggests. Unfortunately it doesn't seem like multi binding is supported in UWP applications.
That leaves me with a couple of options.
Create two text blocks that are bound to each variable and align them next to each other. I'm not sure if i need two extra textblocks to be able to display "lat" and "lng" in front of the values. And then an third label displaying "Position" in front of that again. This answer states that there is no stringformat property for Binding. A total of five textblocks is too much in my opinion.
<RelativePanel>
<TextBlock x:Name="EquipmentLatTextBox"
Text="{Binding Equipment.lat}"/>
<TextBlock x:Name="EquipmentLngTextBox"
Text="{Binding Equipment.lng}"
RelativePanel.RightOf="EquipmentLatTextBox"/>
</RelativePanel>
Create a value converter.
This also seems very unnecessary. I get the point of using converters to convert across data-types, but for concatinating strings there should be a buildt in property.
Create a property in the view model that returns a string of the values as it should be displayed. This seems like the best option as the method is not in the model, but i still think that i should be able to do this in the xaml markup.
Is there a better way to do this?

This can be solved by using runs. It's actually a lot easier to achieve this in UWP than with multi-binding in WPF. A TextBlock item can consist of several "runs" of text which can bind to different properties. The runs will behave like inline elements. Each run can have text directly between the tags, or as a text property. Each run-element can also have independent styling.
Documentation for the TextBlock class
For the example i provided in my question, i ended up formating it like this
<TextBlock x:Name="LocationTextBlock">
<Run FontWeight="Bold">Location: </Run>
<LineBreak />
<Run>Lat: </Run>
<Run Text="{x:Bind ViewModel.Equipment.Lat}"></Run>
<Run> Lng: </Run>
<Run Text="{x:Bind ViewModel.Equipment.Lng}"></Run>
</TextBlock>
The result looks like this
Location:
Lat: 00.000 Lng: 00.000

No, the Universal Windows Platform currently doesn't support multi binding. The best solution for you is indeed creating a dedicated property in the view model or alternatively using the two TextBox controls. As compared to WPF the binding syntax in UWP is more limited to ensure the best performance possible.
You could also consider using the x:Bind syntax to ensure strongly-typed and optimized bindings, which were introduced with UWP.

Related

UWP MVVM XAML Dynamic UserControl Manager

I need help with a change of perspective.
I got stuck trying to approach UWP in a way I used to do in WPF regarding a MVVM pattern for managing UserControls dynamically.
I naturally tried to perform the same pattern in UWP but got stuck on various things like UWP not supporting 'x:Type' ...
Situation is; time to rethink this approach and look for a new direction. Seems I'm forced to abandon to use implicit binding in a similar fashion to the WPF pattern, using the Content property of a ContentPresenter and a VM property 'of type Object', which maintain a selected ViewModel. It was a simple and clean approach for matching up the correct View automagically with the VM set in ActiveViewModel.
the below was such a simple way of managing many views all over the place, odd MS not fixing this? But, back to the big Q: what now in UWP!?
<ContentPresenter Content="{Binding ActiveViewModel}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:OneViewModel}">
<local:OneView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:TwoViewModel}">
<local:TwoView />
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
What Shall I do instead of this!? Anyone found a new efficient way of doing it? I got stuck in my stubborn mind and need someone to kick my butt so I go forward. Getting to old to change, but due to this profession it seems I constantly have to. :)
Looking at the DataTemplate documentation, there's a paragraph explaining the situation which you are trying to figure out.
For advanced data binding scenarios, you might want to have properties
of the data determine which template should produce their UI
representations. For this scenario, you can use a DataTemplateSelector
and set properties such as ItemTemplateSelector to assign it to a data
view. A DataTemplateSelector is a logic class you write yourself,
which has a method that returns exactly one DataTemplate to the
binding engine based on your own logic interacting with your data. For
more info, see Data binding in depth.
Here, you have an example on how you can select distinct DataTemplate for items in a control such as a ListView based on defined conditions.
Your situation is a bit different from the one described above, but the solution should be within what is explained above.
Create a class which derives from DataTemplateSelector, and override the SelectTemplateCore methods exposed by it, where you define the logic of what DataTemplate should be selected for the specific presented object.
This Derived class should expose properties of type DataTemplate, which identify each single DataTemplate template object, you pretend to be able to choose from.
Just as in the example, you are probably better of by defining the DataTemplate resources on an higher level object, such as the Page itself.
Instantiate your DataTemplateSelector Derived class in XAML as a resource and set each of the properties exposed above of type DataTemplate to the analogous DataTemplate static resource.
Utilize the ContentTemplateSelector dependency property, by setting it your custom DataTemplateSelector.
With this logic, it should be possible to have your ContentPresenter decide correctly between which DataTemplate it should choose from, based on your required UI logic.

UWP X:Bind and Design Time Data

is it possible to use x:bind and design time data in uwp apps?
e.g if I had a textbox that used x:bind to bind to a property on viewmodel in the code behind, should that property's value appear in the textbox in the designer?
is there a way of achieving this?
cheers
Johnny
x:Bind doesn't support design-time data yet. Maybe it never will given it's designed for compile-time bindings to boost performance (I wish it would though).
For simple UI testing purposes, I would add a FallbackValue to the binding expression to force the designer to show me some dummy text. However, don't forget to remove it once you are done with the design.
<TextBlock Text="{x:Bind MyMoney, FallbackValue='$10,000,000'}" />
Update
Now it's easier with the new design-time data support.
<TextBlock Text="{x:Bind MyMoney}" d:Text="$10,000,000" />
Read more from here.

What's the DataContext of the Header elements inside a Hub control?

I have started to develop for WP 8.1 using Windows Runtime recently, and I have faced a... "problem" that I don't seem to understand.
The application I am currently developing uses a Hub control, and I would like to tweak its header's appearance slightly. To do so, I changed the HeaderTemplateattribute of the Hub control. However, as I tried to localize the textual content of the header (note that this is WinRT, the localization process is slightly different from the process in WP8 and can be found here), I "accidentally" fixed the problem by making the template like this:
<Hub.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
Foreground="Red"/>
</DataTemplate>
</Hub.HeaderTemplate>
I don't understand why it worked, though. When you do data binding like this (just using the expression {Binding}), doesn't the element get the same DataContext as its father? What's happening under the hood? Who's the parent element of the TextBlock, after all?
Thanks in advance.
EDIT
As igrali asked, here is a more complete view of the XAML:
<Page ...
DataContext="{Binding Data, RelativeSource={RelativeSource Self}}">
<Grid Background="#FFF6DB">
<Hub Name="MainPageHub"
x:Uid="MainPageHub"
Margin="0,27,0,0">
<Hub.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
Foreground="White"/>
</DataTemplate>
</Hub.HeaderTemplate>
...
Then, in the /Strings/en-US/Resources.resx, I have a "MainPageHub.Header" property set to "foobar" (just an example), and what I get as a header is actually "foobar" (which is what I wanted, but even so it seems confusing!).
As Tim Heuer explains it here
Notice the x:Uid value here. This now maps back to the key in your
RESW file. Anything with that starting key will have properties
merged into it. So we can have a key in our RESW for “Text” using the
key name MyTextBlock.Text with a value of “Hello World” and the
runtime will do the replacement for you. This applies to properties
other than text (i.e. width) as well as attached properties.
All I can add is - notice the x:Uid. It's MainPageHub. In the localized resource file, you have a MainPageHub.Header. This means that the value of the resource string will be set to the Header of the control which has the x:Uid set to MainPageHub.
So, now that it's clear how the Header is set - there's still the binding part. Well, considering you have a different template for the Header, it needs to do the {Binding } part to actually get the value of the header which is set through the resources.

Windows 8 bottom app bar

I've been trying to get an App bar implemented in a WinRT metro app (C# / XAML), but don't know where to begin. I've tried using the <ApplicationBar/> tag and I get a Type not found error.
There's no help online, could someone update this post with the answer so that it'll serve as a reference to other programmers as well?
There's only a JavaScript sample which isn't of much help.
This should work:
<AppBar
VerticalAlignment="Bottom">
<Button
AutomationProperties.Name="Play"
Style="{StaticResource PlayAppBarButtonStyle}"
Command="{Binding PlayCommand}" />
</AppBar>
– you would put that in the layout root grid of your page.
*EDIT
Note: According to documentation - you should put it in Page.BottomAppBar property, although at least in Windows 8 Consumer Preview - it works fine when used in any Grid, which is convenient if your UI isn't tightly coupled to a Page control.
*EDIT 2, response from MSFT:
The recommended approach is to use the Page.BottomAppBar/TopAppBar properties.
There are known hit-testing issues in the Consumer Preview if AppBars are added without using these properties
The AppBars do not use the proper animations if they are added without using these properties
If AppBars are added as children of arbitrary elements then it's easier for multiple controls to attempt to create/modify AppBars, resulting in an inconsistent user experience
*EDIT 3
The CustomAppBar in WinRT XAML Toolkit can be used anywhere, animates based on Vertical/Horizontal-Alignment, can have other content overlaid on top of it and also has a CanOpen property that allows to block it from opening.
<Page.TopAppBar>
<AppBar>
<TextBlock x:Name="TextBlock1" Text="Sample Text" Margin="0,0,0,0" Height="Auto" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</AppBar>
</Page.TopAppBar>

Closing nested tabs using WPF?

I'm trying to design a UI that contains nested tabs, but I can't seem to find information on how to remove the nested tabs in an MVVM fashion.
Here's my XAML (snipped for brevity):
<TabControl Name="ProjectTabControl" DockPanel.Dock="Top" ItemsSource="{Binding ProjectTabs}" IsSynchronizedWithCurrentItem="True">
<TabControl.ContentTemplate>
<DataTemplate>
<TabControl DockPanel.Dock="Top" ItemsSource="{Binding FileTabs}" Padding="1">
<Button Command="{Binding CloseTabCommand}" CommandParameter="TabItem" />
</TabControl>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
My question is: what argument(s?) should I be passing in CommandParameter, and how would I affect it in the ViewModel to properly remove the tab?
It doesn't look like you have a solid understanding of how to implement an M-V-VM pattern in WPF. It looks like you know understand DataBinding but the pattern your sample demonstrates seems to be missing an understand of ViewModels and Commands, which are really required for MVVM.
Review the article linked below and the sample application it uses. You should find what you're looking to do is demonstrated here and is pretty easy to implement.
The Model-View-ViewModel (MVVM) Design Pattern for WPF
I hope that this doesn't seem like a cop-out but it would require a significant amount of re-posting of the linked article to get you where you want to go. Go read the article, work through the sample and if you still have problems, post on this question and I'll make sure to watch for it.