Binding to ElementName depends on binding order - xaml

I created simple StateTrigger to bind to FrameworkElement Width property. There are three dependency properties: MinValue, MaxValue and Element. They types are double, double and FrameworkElement accordingly.
And I noticed that depending on binding order it may or may not work.
This works fine.
<local:ElementWidthTrigger MaxValue="1000"
MinValue="800"
Element="{Binding ElementName=LayoutRoot}" />
And this is not.
<local:ElementWidthTrigger Element="{Binding ElementName=LayoutRoot}"
MaxValue="1000"
MinValue="800" />
Noticed that only difference in this two samples is Element property binding order.
In ElementWidthTrigger there is property changed callback for each dependency property. And when Element at the very top it's callback never called no matter what.
x:Bind solves this issue no matter what order is in use but a question remains. Can anyone explain why Element property is failing to bind depending on binding order?
Running on Windows 10 1803 build 17134.320.
Working example project can be found here.

Thank you reporting this issue and providing a solid repro project - this is a platform bug. I have logged it in our database and assigned to the right team. Thanks again!

Wow, this is an enigma! While I haven't been able to find out the reason for the problem, it really does seem like a bug in UWP. I have noticed that the simple act of adding a x:Name to one of the VisualStates will make even the ElementName-first order work as expected:
<VisualState x:Name="Test">
<VisualState.StateTriggers>
<local:ElementWidthTrigger Element="{Binding ElementName=LayoutRoot}"
MaxValue="1000"
MinValue="800" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Rectangle.Fill" Value="Blue" />
</VisualState.Setters>
</VisualState>
It would be great is someone from the UWP team saw this and helped out, as it probably requires insight into the internals to understand what is going on.

Related

How to Override the property value in the transform file in WIX during Installation

I am looking for a suggestion How to Override the property value in the transform file in WIX during Installation.
Basically we have a property - for example USE_WINDOWS_AUTH
Consider that, Transform file (.mst) has USE_WINDOWS_AUTH=1
Now the requirement is, let the property value in transform be whatever, but WIX code should override it to USE_WINDOWS_AUTH=0 .
Reason for such requirement is, there is an enhancement happened in the product and clients are still using old properties , which is causing us lots of issues.
So the installer should ignore/override the property value of .mst file.
We tried After="CostFinalize", Before= "InstallInitialize" and etc. NO luck
<SetProperty After="CostFinalize" Id="USE_WINDOWS_AUTH" Value="0"/>
Another observation is, we are facing issue in silent mode (/quiet), but not interactive mode..
not sure what I am missing..
Any suggestions or advise please..
Please let me know if I can provide you any other information on this.
Thanks In Advance..
Rajkumar.
After further investigation seems to be below logic is helping me to serve the requirement. Hence Posting here.. which may help someone looking for some clues to the similar requirement.
<CustomAction Id='ModifyWindowsAuthValue' Property='USE_WINDOWS_AUTH' Value='0' Execute='immediate' />
<InstallExecuteSequence>
<Custom Action='ModifyWindowsAuthValue' Before="CostFinalize"/>
//existing other actions
</InstallExecuteSequence>

How do I set ListView's `ScrollViewer.HorizontalScrollMode` in codebehind?

I want to customize a ListView's ScrollViewer.HorizontalScrollMode from codebehind. How can I do this?
It is easy in XAML:
<ListView
x:Name="MyListView"
ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollMode="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<!-- ...-->
</ListView>
But how could I do this in C# or C++/CX codebehind?
Disclaimer: I work for Microsoft.
The ScrollViewer properties (like VerticalScrollMode, VerticalScrollBarVisibility, etc) are attached properties (just like AutomationProperties are).
XAML actually provides two methods of setting these properties:
The property system (SetValue and GetValue)
The XAML accessor pattern
I find the SetValue pattern super straightforward:
// C++/CX
this->MyListView->SetValue(ScrollViewer::VerticalScrollModeProperty, ScrollMode::Disabled);
this->MyListView->SetValue(ScrollViewer::VerticalScrollBarVisibilityProperty, ScrollBarVisibility::Hidden);
this->MyListView->SetValue(ScrollViewer::HorizontalScrollModeProperty, ScrollMode::Disabled);
this->MyListView->SetValue(ScrollViewer::HorizontalScrollBarVisibilityProperty, ScrollBarVisibility::Hidden);
(I have not used the other pattern).
This method works for all AttachedProperties (see this similar StackOverflow question).
This works because attached properties are, at their core, DependencyProperties, which provide the SetValue and GetValue APIs. From the documentation of attached properties:
Attached properties for the Windows Runtime are implemented as dependency properties, so that the values can be stored in the shared dependency-property store by the property system. Therefore attached properties expose a dependency property identifier on the owning class.

How to scale fonts in UWP XAML app based on resolution scaling using "resource system"

The documentation for FontSize indicates that you can using different font sizes for different scalings using "the resource system." Unfortunately, it does not elaborate on how one would do that or what exactly it means by "the resource system."
I have seen some guidance on this stackoverflow question, but that appears to use converters to solve the problem.
Is there another, better, way to do this using "the resource system?"
The value type of FontSize is double. so you could make double type resource dictionary.
<Application.Resources>
<ResourceDictionary>
<x:Double x:Key="SmallFontSize">20</x:Double>
<x:Double x:Key="BigFontSize">40</x:Double>
</ResourceDictionary>
</Application.Resources>
For usage
<TextBlock FontSize="{StaticResource SmallFontSize}" Text="Something"><TextBlock>
For dynamically change a FontSize resource value for UWP. Please refer this reply.

How to bind an event to a command in a Universal App using the MVVM pattern?

I hope somebody can help.
I've spent some time researching the best way to bind an event to a ViewModel command using the MVVM pattern when developing a Universal App. I'm using MVVM Light.
As a test I'm using the SelectionChanged event of a ComboBox.
I've read a few people that have pinched the Behaviours SDK from the Windows 8.1 / WinRT framework and had some success with that. I have also included the Universal App behaviours SDK in my project and tried the following (put together from Windows 8.1 examples but using the UWP SDK).
XAML
<Page
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core" />
...
<ComboBox ItemsSource="{Binding InputQuantities}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="SelectionChanged">
<core:InvokeCommandAction Command="{Binding SomeComboBoxCommand}" CommandParameter="Foo" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ComboBox>
View Model
public RelayCommand SomeComboBoxCommand {get; set;}
However, the core:InvokeCommandAction isnt part of the Behaviours SDK and i get Invalid Type: expected type is 'Microsoft.Xaml.Interactivity.ActionCollection'. I've tried to use an ActionCollection.... but I'm not sure I know what I'm doing with that.
Ive successfully got it to work with compiled bindings and using Laurent's Blog Post:
XAML
<ComboBox ItemsSource="{Binding InputQuantities}" SelectionChanged="{x:Bind Vm.SomeComboBoxCommand }" />
View Model
public void SomeComboBoxCommand(object sender, SelectionChangedEventArgs e){//do stuff}
I know this isnt what Laurent is intending to demonstrate here and I think doing this is breaking the decoupling of the view and VM by then having to reference a UI component in my view model to get the selected item. But I've seen references to doing this during my research.
So how can I get this working using The Universal App interaction behaviours, if that's the right way to do it of course?
Update 1.
This is what I attempted to add, believing, incorrectly that I was adding the universal app behaviours SDK. I didn't notice at the time that it was targeting Windows 8.1.
However, my questions still stands: Why wont the InvokeActioncommandwork and why is it throwing the mentioned error? I will look at the other posts as soon as I get to work.
Update 2
After testing this on my works PC (exact same code as above, 1st example and the same behaviours SDK) it works fine and I'm getting the behaviour that I would expect. I need to test again on my home PC to see what has gone wrong. (Thanks to Justin XL for sticking with me)
Update 3
For completeness, after returning home I got the latest version of my project (from being checked in on my works PC) and it now also works on my home PC. I'm not sure what state my Visual Studio was in but it had sufficiently confused me enough to post this question. At least this should serve as a document on how to do what is described in the title. Thanks for all your help.
We seem to be getting this question a lot lately, in several different variants...
I'm not familiar with Universal App but is there any specific reason you're trying to use an event? WPF/Silverlight etc are designed to be data driven, all you need to do is bind the ComboBox's SelectedItem member to a property in your view model and the setter will get called whenever the user selects a new item. Often times you have to do exactly the same processing in response to other parts of your view model changing it (e.g. in Master-Child views) so having that logic in a single place generally makes for a much cleaner architecture.
Check this link: MVVM EventBinding Library ,explains about MVVM EventBinding. This purely decouples the View & View model & pass only the arguements to the command.

How to add an Array in WinRT XAML

I am looking to declare an array in XAML. I can do this in WPF. Just can't seem to find the right namespace in WinRT. Anyone know?
<Page xmlns:list="?Something?">
<Page.Resources>
<x:Int32 x:Name="MyScalarValue">123</x:Int32>
<list:Array x:Name="MyValueList">
<x:Int32>123</x:Int32>
<x:Int32>456</x:Int32>
<list:Array>
</Page.Resources>
</Page>
x:Array (and x:Static and a few other ones) aren't presently supported in WinRT. For that matter, x:Array isn't supported in Silverlight either, despite developers pushing for it.
Given the fact that the XAML implementation for WinRT appears to be more closely aligned with SL than WPF, this isn't too surprising.
Edit - some more info regarding SL4+ vs. WPF differences:
"Notable omissions here that exist in WPF or [MS-XAML] are x:Array, x:Code, x:Type, and code access modifiers."
Also, a delta between SL4 and the WinRT implementation here, and its associated links, makes it clear that these bits didn't magically make it into WinRT when they were (and still are) omitted from SL.