UWP - Get Slidervalue from another Page - xaml

I've got 2 Pages: My Main-Page and my Settings-Page - both in XAML and xaml.cpp as code behind. I've also got a class where I want to work with the values of the Settings-Class. (As I already asked in another post) I can save the values from the Settings-Page in the cache using the XAML-tag NavigationCacheMode="Enabled". Using this my SliderValue stays the same even when I switch to my Main-Page and back again to Settings-Page.
What I want to do now: Save the value of the slider as soon as it is changed and store this value to a variable to which I have access from a third Class.
What I've got so far (not working, always showing initialvalue '70'):
Settings.xaml.cpp:
UWPApp::Settings::Settings()
{
InitializeComponent();
quality = sldQuality->Value;
}
int Settings::getQuality() {
return quality;
}
void DirectX12XamlApp::Settings::sldQuality_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
quality = sldQuality->Value;
}
In Settings.xaml.h:
public:
Settings();
int getQuality();
private:
int quality;
In Settings.xaml:
<Slider x:Name="sldQuality" ValueChanged="sldQuality_ValueChanged" HorizontalAlignment="Left" Margin="38,325,0,0" VerticalAlignment="Top" Width="168" Value="70"/>
//initial-Value = 70, which is ALWAYS showing when using getQuality() in an other Class
In my logicclass I want to use it like this:
int quality = Settings::getQuality();

Quick answer: save the value of the slider in a public static property, ideally in the separate class.
Recommended answer:
You should use MVVM structure in your app, so you would have a separate layer for storing your settings data. You can save the value of the slider in the singleton service, ideally injected through the IoC container. You may also want to save it in the local storage so the settings are saved when the user closes the app.
MVVM is really a standard of XAML-based apps, and the concept is not difficult to learn and implement.

Sounds like you're looking for a way to store and retrieve settings data for your app. Features for that have been built into the UWP. Please refer to this article from the Windows Dev Center. Examples on that page are for C#, but all the links to UWP API references contain code snippets for C++ as well.

Related

UWP Localization Using One Resource

So I'm attempting to add localization to the UWP application I'm working on. From what I've researched online I'm able to add it using the Mulitlingual App Toolkit. The one issue I run into is duplicate values in the resource file. For example imagine I need to label 2 different controls with the same value. The controls are a button (using the property button.Content) and a text block (using textBlock.Text). I'd like to only have one name/value pair in the resource file that can be used for both of these controls. Is there a way to do this? Also I'd like to be able to set these values in xaml. Thanks in advance.
Localization for UWP in general
First, the default way of internationalization (i18n) and localization (l10n) is by using different .resw (or .resx for other environments like Xamarin) per language. In these files you store translated strings with some identifier key.
The Mulitlingual App Toolkit is a tool to facilitate and somewhat manage (e.g. tracking review status) the surrounding processes of actually translating the strings with people that possibly are not part of the actual dev team. But in the end, it too just generates the .resw files like you could have done manually. So you don't HAVE to use the MAT in order to localize your App.
Implementing it
The way to achieve what you want would be to use some sort of Binding.
I personally like to use a custom markup extension to be able to distinguish between actual dynamic data and hardcoded internationalized strings. Furthermore it keeps the Binding short. This would then look something like Title="{i18n:Translate GlossaryPageTitle}".
Unfortunately, Markup Extensions don't seem to be available in UWP as of yet (source).
So the way to go (simpler anyway) is to use a Converter and pass the Key for the desired Text as a parameter.
Like this:
Title="{x:Bind Converter={StaticResource LocalizationConverter}, ConverterParameter=GlossaryPageTitle}".
Where the implementation of the converter would look like this:
public class LocalizationConverter : IValueConverter
{
private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForViewIndependentUse("/Resources");
public object Convert(object value, Type targetType, object parameter, string language)
{
if (parameter is string resourceId)
{
return _resourceLoader.GetString(resourceId);
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotSupportedException();
}
}
Then register the Converter somewhere in your App (either per view or globally) and you're good to go.

Mobile Specific Views / Device Detection

In the .NET Core docs there is a page titled "Building Mobile Specific Views" but is under construction: https://docs.asp.net/en/latest/mvc/views/mobile.html.
Does anyone have some insight on building mobile views or successfully doing device detection?
Serving specific views based on the browser's user-agent is an outdated concept as it do not sufficiently says much about the capabilities of the device. For example, iPhone and iPad come in different screen sizes and even mobile browsers allow to change the user-agent.
The new concept is called Responsive Design where one creates a single page that fits and show/hides certain element based on the available screen width. One popular responsive deisgn CSS Framework is Bootstrap, originally developed by Twitter and later open-sourced.
Here is an example of responsive design. When you go to the site and change the width of your browser, the design updates as well from 3 to 2 to 1 column design with browser or mobile like navigation (with the Hamburger menu).
This feature actually was not implemented by microsoft. There is couple open discussions for this question:
https://github.com/aspnet/Mvc/issues/4877
https://github.com/aspnet/Razor/issues/751
As a generic answer from them - use responsive web design and css media queries (which from my point of view is not perfect answer for team that claims himself for building general web framework).
There is a implementation for this feature exist as pull request - https://github.com/aspnet/Mvc/pull/4878.
Since this pull request seems to be forgotten, i extract this code into separate project which is available on
https://github.com/laskoviymishka/MvcDeviceDetector.
You may use this implementation (which is easy to add to exist MVC project) or implement this itself. This is pretty easy - you need just implement and reqister own IViewLocationExpander for that.
This can be handle in .Net Core using RazorViewEngineOptions
1) Create Service LocationExpanderService.cs
public class LocationExpanderService : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context,
IEnumerable<string> viewLocations)
{
//replace the Views to MyViews..
var viewLocationsFinal = new List<string>();
if (!string.IsNullOrEmpty(context.Values["viewCustom"]))
{
foreach (var viewLocation in viewLocations)
{
viewLocationsFinal.Add(viewLocation.Replace(".cshtml", ".mobile.cshtml"));
}
}
viewLocationsFinal.AddRange(viewLocations);
return viewLocationsFinal;
}
public void PopulateValues(ViewLocationExpanderContext context)
{
var userAgent = context.ActionContext.HttpContext.Request.Headers["User-Agent"].ToString().ToLower();
var viewCustom = userAgent.Contains("android") || userAgent.Contains("iphone") ? "mobile" : "";
context.Values["viewCustom"] = viewCustom;
}
}
2) Configure services in startup.cs
services.Configure<RazorViewEngineOptions>(o =>
{
o.ViewLocationExpanders.Add(new LocationExpanderService());
});
3) Create view with .mobile extension
Index.mobile.cshtml

Source code for WinRT UI controls publicly available?

Is the source for Windows Store (WinRT) UI controls publicly available? We would like to extend some of the controls and not have to start completely from scratch, like we can for SL and WPF. Googling and looking through SO doesn't turn up anything for Windows 8.
Thanks!
So unlike WPF, [WinRT-XAML] controls are written in C++/CX.
But, it sounds not so much like you want the source code as much as you want to derive from existing controls and extend or override their functionality. You know you can do this, right? It's easy enough and sounds like you will get the results you are asking in your question.
Something like this:
public class MonkeyTextBox : TextBox
{
public new string Text
{
get
{
return "Always Monkeys!";
}
set { /* do nothing */ }
}
}
This is my custom TextBox wherein I have replaced the base implementation of Text with my own. Granted, I hope your custom controls are better. Anyway, you can do this with almost every control, and you can add your own properties and events. Make sense?
Reference: http://blog.jerrynixon.com/2013/01/walkthrough-custom-control-in-xaml-isnt.html
But to answer your question: no, we have not released the source (yet). Hopefully, that will save you the time looking for it. Maybe someday we will - maybe.
Best of luck!

Viewing a BitmapImage for Sample Data in Design Mode in Blend 2012

Is there a way to create a BitmapImage as Sample Data to be used in Blend 2012 Metro Store App (on Windows 8)?
I have a ViewModel as follows:
public ItemDesignDataVM()
{
WebThumbnail = new BitmapImage(new Uri(???));
}
public string ItemId { get { return "123456"; } }
public BitmapImage WebThumbnail { get; private set; }
And would like to bind to it within Xaml like this:
<Page.Resources>
<DesignData:ItemDesignDataVM x:Key="ItemDesignDataVM" />
</Page.Resources>
<TextBox Text="{Binding ItemId}" />
<Image Source="{Binding WebThumbnail}" />
The problem is that no matter what I pass to the BitmapImage constructor it fails to get created. I've tried various different relative paths and an absolute path too.
If I attach to the XDesProc.exe process and debug that code path the BitmapImage.PixelHeight and PixelWidth are 0 which I think means they haven't been loaded.
My binding is correct as I'm seeing the ItemId coming up in the designer.
Any help would be appreciated.
I don't know if that is actual code or pseudo code, but I see a couple issues with what you've posted.
First, your WebThumbnail property doesn't support change notification. Since the property is set in the constructor you should be OK, but if you later decide to make this happen asynchronously then the property could get filled in after binding occurs, and without change notification the UI would never update.
Next, although you've created the ViewModel as a Page resource, I don't see anywhere that you've set it as the DataContext for the page. The ViewModel doesn't necessarily have to be set as a resource, it can be set directly on the DataContext or d:DataContext properties. Since you're saying that you see the ItemId, you either have xaml or code elsewhere to wire this resource up to the DataContext or you may have a default value in the textbox?
As to why the PixelWidth and PixelHeight are zero, maybe you're checking it right after calling the constructor and before the BitmapImage has actually had a chance to download the image data asynchronously? These values may actually get filled in later, but if you're not setting the DataContext of the page properly you would never see the image.
If that's not actually what's going on, you may have an issue with the URL. First, try the URL of a known image online. Make sure the URL works in your browser and then try it in the code. If the URL is for a local file, there are special prefixes you need to use like ms-appx:/// if the file is embedded in your project, ms-appdata:///local/... if it's in your apps local folder, ms-appdata:///roaming/... if it's in your apps roaming folder, etc. (note the 3 slashes).
Hope that helps...

MEF + SL4 question

I'm working on an app in the Silverlight 4 RC and i'm taking the oppertunity to learn MEF for handling plugin controls. I've got it working in a pretty basic manor, but it's not exactly tidy and I know there is a better way of importing multiple xap's.
Essentially, in the App.xaml of my host app, I've got the following telling MEF to load my xap's:
AggregateCatalog catalog = new AggregateCatalog();
DeploymentCatalog c1 = new DeploymentCatalog(new Uri("TestPlugInA.xap", UriKind.Relative));
DeploymentCatalog c2 = new DeploymentCatalog(new Uri("TestPlugInB.xap", UriKind.Relative));
catalog.Catalogs.Add(c1);
catalog.Catalogs.Add(c2);
CompositionHost.Initialize(catalog);
c1.DownloadAsync();
c2.DownloadAsync();
I'm sure I'm not using the AggregateCatalog fully here and I need to be able to load any xap's that might be in the directory, not just hardcoding Uri's obviously....
Also, in the MainPage.xaml.cs in the host I have the following collection which MEF puts the plugin's into:
[ImportMany(AllowRecomposition = true)]
public ObservableCollection<IPlugInApp> PlugIns { get; set; }
Again, this works, but I'm pretty sure I'm using ImportMany incorrectly....
Finally, the MainPage.xaml.cs file implements IPartImportsSatisfiedNotification and I have the following for handling the plugin's once loaded:
public void OnImportsSatisfied()
{
sp.Children.Clear();
foreach (IPlugInApp plugIn in PlugIns)
{
if (plugIn != null)
sp.Children.Add(plugIn.GetUserControl());
}
}
This works, but it seems filthy that it runs n times (n being the number of xap's to load). I'm having to call sp.Children.Clear() as if I don't, when loading the 2 plugin's, my stack panel is populated as follows:
TestPlugIn A
TestPlugIn A
TestPlugIn B
I'm clearly missing something here. Can anyone point out what I should be doing?
Thanks!
I think most of what you are doing is fine. Although ObservableCollections do support notifications of individual elements being added and removed, MEF doesn't take advantage of this. In your case it will simply clear the collection and then add all the plugins. Since you are using OnImportsSatisfied for the change notification, you don't even need an ObservableCollection. You could just use an IEnumerable for your import.
To add flexibility in downloading different xaps, I would expose a service in your container that can be imported and that provides the functionality to download a xap given a url. Then any component in your container can trigger a download, and the url to download can come from whatever source you deem appropriate.