Use certain style only when the Fall Creators Update is detected - c#

As an example, I would like to apply the ButtonRevealStyle to my button:
<Button Style="{StaticResource ButtonRevealStyle}" Grid.Column="1" Width="38" ... />
This will work, but of course only on a device with the Fall Creators Update installed. How do I disable this for all previous versions of W10?
I know I can use .IsApiPresent() in the code-behind when I want to check for a specific Windows Api but in this case this doesn't seem to be the preferred/recommended solution and I'd like to stick to just XAML for this. Doing it in C# requires referencing every single control with that style in code-behind and manually assigning the style if it's present. I'm pretty sure this is not the best solution in this day and age, where you can set up responsive and animated layouts solely in XAML. Besides, if the button was in a ListView.ItemTemplate just accessing each control would require a few solid lines of code. Not to mention the check itself
Is it possible? Am I missing something?
Edit: Turns out it is possible, and I totally was missing something. Conditional XAML can easily be done and isn't that complex all things considered. It's just a matter of setting a custom namespace in the file (pointing to the same resource as the 'root' namespace, just with the `IsApiContractPresent" check at the end. Yes, it is possible to use that in XAML.
After setting the custom namespace you can then specify attributes that will only be aplied when the certain API is present on the End-User's device. Example:
xmlns:fcu="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
...
<Button fcu:Style="{StaticResource ButtonRevealStyle}" Grid.Column="1" Width="38" ... />
This will result in the button getting Reveal only on PCs with Fall Creators Update and the previous versions won't be throwing an error.
More info: https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/conditional-xaml
You people clearly like your downvote button a bit too much.

Turns out it is possible, and I totally was missing something. Conditional XAML can easily be done and isn't that complex all things considered. It's just a matter of setting a custom namespace in the file (pointing to the same resource as the 'root' namespace, just with the `IsApiContractPresent" check at the end. Yes, it is possible to use that in XAML.
After setting the custom namespace you can then specify attributes that will only be aplied when the certain API is present on the End-User's device. Example:
xmlns:fcu="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
...
<Button fcu:Style="{StaticResource ButtonRevealStyle}" Grid.Column="1" Width="38" ... />
This will result in the button getting Reveal only on PCs with Fall Creators Update and the previous versions won't be throwing an error.
More info: https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/conditional-xaml

Related

How to use different panels in a grouped list view?

I need to use a different panel for a particular section/group in my ListView. How do I do that (using XAML, C#, or anything)? I already tried using GroupedStyleSelector but it didn't work (I researched about it but it turned out it's not designed for this purpose). Here's my XAML right now:
<ListView ItemsSource="{Binding Source={StaticResource cvs}}">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.Panel>
<ItemsPanelTemplate>
// I want to change this for a particular group
<uwp:SGStaggeredPanel/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
I'm thinking of subclassing the panel, but the problem is how do I get a reference to the current group?
https://learn.microsoft.com/en-us/windows/communitytoolkit/extensions/listviewbase
The above article talks about a WCT goody that allows you to dynamically change the Tamplate of the item that is about to be rendered, this particular example is a statically expressed extension that simply works as an attached property to a listview and cycles through two different templates
But you can easily extend ListView into a templated control and then more easily have access to the Viewmodel that houses your Itemsource, from then you can go on to change the
private static void ItemTemplateContainerContentChanging(Windows.UI.Xaml.Controls.ListViewBase sender, ContainerContentChangingEventArgs args)
which is where all the magic takes place.
Notation for implementation
Note 0:
if you don't know mvvm and binding, forget you ever read this and go study it up instead.
Note 1:
All child controls that have no explicitly defined Data Context will inherit their parents.
Note 2:
You will be able to Map incoming controls in the aforementioned function by tracking the incoming args.ItemIndex and then cross checking it with the binded source (Observable list etc) that is housed on the underlying datacontext.
Note 3:
To convert this into a tamplated/custom control you will have to pretty much make your own implementation of ListView like this MyListview:ListView
The Dependency properties will have to be converted to conventional ones,
just type 'propdp' and double tap Tab, to bring up the default tamplate.
You will still have to reference all the different DataTamplates from XAML like its shown in the showcase app listed bellow.
Note 4:
Cut the slack off that showcase code, the stretch direction and the zebra stripes for example are not needed in your case.
https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI/Extensions/ListViewBase/ListViewExtensions.cs
this is the exact location of the code piece i talked about, to check it out in action and play with it, Download 'Windows Community Toolkit' from the store, it is in the Extensions section.

WP8 - C# - Getting object value from Telerik RadPickerBox

I am currently having an issue regarding this component.
This is the xaml usage of it in my app:
<telerikPrimitives:RadPickerBox x:Name="box_change" Width="0">
<StackPanel Background="White">
<StackPanel Height="618">
<PasswordBox Name="NewPassword1" Padding="2,8,2,8" Margin="10,0,10,0" Style="{StaticResource PasswordBoxStyle}" />
</StackPanel>
</StackPanel>
</telerikPrimitives:RadPickerBox>
I am currently in need of retrieving, from my C# code, the value "password" of the field "NewPassword1", still I am unable to do that.
I already tried retrieving it with something like this:
box_change.NewPassword1.Password
but, of course, else I wouldn't be asking this question right now, this way doesn't work.
What would you suggest to retrieve the value?
Thanks in advance,
Guido
this.NewPassword1.Password
Glad to help!
Have you considered using Telerik's RadPasswordBox for WP8? It's optimized for passwords with masking characters and other features (and easily provides you with the password):
var userEnteredPassword = myPasswordBox.Password;
That being said, even though your PasswordBox is the child of two StackPanels, you can access the Password box in the same scope via NewPassword1. If you have more complex controls see the control's documentation on how to get the value of a child element.

Data binding the Text property of a Run

I'm trying to databind a Run of a TextBlock in code at runtime, and I can't for the life of me figure out how.
Several sources on the internet suggest this isn't possible without some (not too pretty) additional workarounds, and, more importantly, it should completely fail when you try to do it in XAML.
Yet, in my application I have the following, which works beautifully:
<DataTemplate x:Key="PitchTemplate">
<Grid Width="120" Height="120" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center">
<Run Text="{Binding}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="36"/>
<LineBreak/>
<Run Text="{Binding Frequency, StringFormat=\{0:n2\}Hz}" FontFamily="{StaticResource PhoneFontFamilyNormal}" Foreground="{StaticResource PhoneSubtleBrush}"/>
</TextBlock>
</Grid>
</DataTemplate>
So I figured: If it can be done in XAML, it should be possible to do it in code.
Sofar, to no avail. Using the "regular" way of binding in code won't work; the Run class doesn't inherit from FrameworkElement, so doesn't have a SetBinding method, and it's Text property is not a DependencyProperty.
Using BindingOperations.SetBinding doesn't work because the Text property is not a DependencyProperty.
I'm up to the point that I'm willing to accept that it can't be done at runtime (although not without a last attempt at StackOverflow), but I'm still curious if
This can be done in code at runtime?
And if not:
How come it does work in XAML?
EDIT:
The example shown is just there to show that it can be done in XAML. The reason I need to create the bindings in code, is that I have a control that dynamically creates other elements, which need to be data bound.
UPDATE:
As Pete and I both found out, there is a dependency property for Text, but it's private. I assume that's why it does work through XAML (the xaml parser probably has more rights when it comes to reflection, and more knowledge in general about classes).
The upside is, that this means (tried & tested) it also works through XamlReader.Load(), which is (sofar) the cleanest solution I've come up with.
But if anyone has anything better, I'd be glad to hear about it.
Run.Text is backed by the private TextProperty which means you can't directly set its value without some reflection gimmicks, something like this:
Run r=new Run();
r.Text = "Moo";
var field=r.GetType().GetField("TextProperty", BindingFlags.Static | BindingFlags.NonPublic);
var dp=field.GetValue(null) as DependencyProperty;
BindingOperations.SetBinding(r, dp, new Binding {...});
This is rather ugly, but perhaps it can be useful.
You can find various workarounds for this. This SO post uses a custom attached property to configure binding. The attached property is used because Run is a sealed class in Silverlight so you can't create you own Run that supports binding.
The reason that it works in XAML but not in code-behind might be that there is a dependency property for Text, but it is private. It's a little bit 'black magic' to me though, so that's just a guess! This is a strange one, as in WPF the Run does inherit from FrameworkContentElement and has a SetBinding method...
Could you create a subclass of Run that contains a public DependencyProperty for text? I'm afraid I don't have the Silverlight dev tools to hand to try it out at the moment, but I'll try and take a look later.
Thanks both to Pete & Panagiotis for their efforts and suggestions (both 1 up).
In the end, I decided to go with my own solution (found in the "Update" section of the question): Create dedicated XAML strings containing the Run including the binding, and use XamlReader.Load() to parse it, and return a Run object.
The situation I'm working on is quite specific, so a local solution to the problem is good enough (for now). Reflection, as suggested by Panagiotis, won't work due to restrictions imposed by Silverlight. Lastly, the BindableRuns solutions would need either extensive work to deal with nested properties, or I would have to "uglify" my view model, so I discarded it (also for now).
Thanks all for your input.

Finding the cause of Style problems

In a large WPF-project setting padding on buttons does not have any effect what so ever. No styles, templates, etc are set on the button, but still it won't use my padding.
<StackPanel>
<Button Padding="20, 20">Hello</Button>
</StackPanel>
I tried this in a brand new project and it works like a charm. Obviously there is some global style, template somewhere in the project causing this. Either somewhere in the xaml file, or in some resource file. As this project is rather hefty I going through everything is not feasable.
How to I debug this? Can I see what is overriding the padding?
I tried snooping around with Snoop 2.7.0, but it didn't really tell me much. Any hints on how to proceed with this type of error?
EDIT
I loked at the ValueSource for some properties:
Padding=Local
ContentTemplate=Default
Template=Style
What about the method DependencyPropertyHelper.GetValueSource?
http://msdn.microsoft.com/en-us/library/system.windows.dependencypropertyhelper.getvaluesource.aspx
There is a page on Dependency Property Value Precedence in the MSDN.
Why is it important? few people really know the order of precedence when it comes to dependency property values.
For example, did you know that whatever value you set in the CoerceValueCallback of a DP will overwrite any other set?
I'd suggest you go over that link and start from top (strongest set, will overwrite anything) to bottom (weakest set, will get overwritten by anything), there's a level in there where your value got set.
But hey, if you look at that list, you'll notice you're already in position 3! local value. So you only have 2 levels up: animation and value coercion ;)
I find your own answer might not be correct as well.
Whatever you put in your Button object will overwrite what's defined in the style.
I guess the reason that the padding you defined inside the button doesn't do anything is because, in your default style, the ContentPresenter is missing this,
<ContentPresenter Margin="{TemplateBinding Padding}"
The padding is the distance between the text and the border of the button, that is, the margin of this ContentPresenter.
this works for me:
<Button>
<Button.Content>
<TextBlock Padding="20" Text="Hello world!" />
</Button.Content>
</Button>
This particular problem was caused by a style defined in a resource included in the App.xaml.
The important lesson here is that styles without the x:Key attribute will affect all elements of the target type as described here.
Performing a solution wide wild card search on <Style*TargetType="*Button yielded a list of potential styles that would affect my button. I found one without the x:Key attribute, commented it out just to try and voila! The padding works.

Difficulty adding a inputscope to a TextBox within a StackPanel

So I'm trying to improve the functionality on a text box, by adding a 'text' style input scope on this occasion, later I will need to add a 'currency' inputscope.
I'm using EB4 as its easier to get direct access to contents within a stack panel, however I keep getting greeted with various errors, even after I follow Bob Tabors Tutorial ( http://channel9.msdn.com/Series/Windows-Phone-7-Development-for-Absolute-Beginners/Adding-Different-Input-Scopes)
See screenshot:
I don't know anything about WP7 input scopes but regarding the error in the screenshot it's due to an invalid closing tag :
<TextBox x:Name="NameTb">
...
<TextBox x:Name="NameTb"/>
Should be
<TextBox x:Name="NameTb">
...
</TextBox>

Categories