question

RodFalanga avatar image
0 Votes"
RodFalanga asked ·

Why isn't the Hourly property being set?

I'm working on a very simple UWP app. I'm using the Template10 framework. The viewmodel for the Main window inherits from Template10's ViewModelBase. Here's the property for Hourly from the viewmodel:

 private float hourly;
 public float Hourly
 {
     get => salaryConvUS.HourlyFloat;
     set
     {
         Set(ref hourly, value); //Template10 method
         salaryConvUS.HourlyFloat = hourly;
     }
 }

And here's the XAML related to the TextBox where I'm binding it:

 <TextBox
     x:Name="HourlyTextBox"
     Style="{StaticResource CommonTextboxStyle}"
     Text="{x:Bind ViewModel.Hourly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnforceNumericConvert}}" />

I've set a breakpoint on the Set() method (line 7) of the C# code. It never breaks at that line. Why not?

uwpuwp-xaml
· 7
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

About this sentence "It never breaks at that line", do you mean when you set a value for Hourly property, the set method can't be trigger or when you changed the value in TextBox, the set method can't be triggered? Can you show more details about your unexpected behavior? I can't reproduce this issue. And can you show the code snippet about the Converter method or provide a simple sample that can be reproduced for us to test?

0 Votes 0 · ·

@RodFalanga Have you solved the issue? Please feel free to contact us if you still have question.

0 Votes 0 · ·

Hi, is there any update?

0 Votes 0 · ·

Hi, do you have other questions?

0 Votes 0 · ·

Hi, I haven't heard from you for a while. Have you solved your issue?

0 Votes 0 · ·
Show more comments
yanxiaodi avatar image
0 Votes"
yanxiaodi answered ·

To use functions with {x:Bind}, your app's minimum target SDK version must be 14393 or later. You can't use functions when your app targets earlier versions of Windows 10.

Try to use {Binding ....} to replace {x:Bind ....}?

FYI: https://docs.microsoft.com/en-us/windows/uwp/data-binding/function-bindings

· 1 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you, Yanxiaidi for responding. I don't think your response answers it, though. I'm not invoking a function in the XAML, as if illustrated in the link you pointed me to. (Thank you for that link! Awesome feature which I wasn't even aware was available in version of the SDK 14393 and higher. I'll remember it and likely use it in the future.) I do call the Template10 Set() function, but from within the Hourly property's Setter.

I just tried changing the binding from x:Bind to Binding. Unfortunately it didn't work. :(

0 Votes 0 · ·
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi, try your converter and test converter like this:

   public class EnforceNumericConvert : IValueConverter
   {
     public object Convert(object value, Type targetType, object parameter, string language)
     {
       return value.ToString();
     }
 
     public object ConvertBack(object value, Type targetType, object parameter, string language)
     {
       float par = 0;
       float.TryParse(value.ToString(), out par);
       return par;
     }
   }
· 3 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I've tried your suggestion, Peter. It does seem to make some difference. I've got to play with it more to see what I can do with it.

0 Votes 0 · ·

What is your current issue? Can you show more details about your unexpected behavior?

0 Votes 0 · ·

What's happening now is when I start typing in something in the Hourly TextBox, say 12. initially it put a 0 in the textbox when I press the 1. Then when I press the 2, it puts a 1 in the textbox. I'm confused by that and don't understand why it's being delayed.

0 Votes 0 · ·
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi Rod, try following demo.

XAML:

 <Page
     x:Class="App05.Page05"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="using:App05"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   <Page.Resources>
     <local:EnforceNumericConvert x:Key="EnforceNumericConvert"/>
     <Style x:Key="CommonTextboxStyle" TargetType="TextBox">
       <Setter Property="Background" Value="LightCoral"/>
     </Style>
   </Page.Resources>
   <StackPanel>
     <TextBox
      x:Name="HourlyTextBox"
      Style="{StaticResource CommonTextboxStyle}"
      Text="{x:Bind ViewModel.Hourly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnforceNumericConvert}}" />
     <!-- TextBlock for testing Hourly value-->
     <TextBlock Text="{x:Bind ViewModel.Hourly, Mode=TwoWay}"/>
   </StackPanel>
 </Page>

And code:

 using System;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Data;
 
 namespace App05
 {
   public sealed partial class Page05 : Page
   {
     public Page05() => this.InitializeComponent();
     public ViewModel ViewModel { get; } = new ViewModel();
   }
 
   public class ViewModel : INotifyPropertyChanged
   {
     private Data salaryConvUS = new Data();
 
     private float hourly;
     public float Hourly
     {
       get => salaryConvUS.HourlyFloat;
       set
       {
         Debug.WriteLine(value.ToString());
         Set(ref hourly, value); //Template10 method
         salaryConvUS.HourlyFloat = hourly;
         OnPropertyChanged();
       }
     }
     private void Set(ref float input, float value) =>    input = value;
 
     public event PropertyChangedEventHandler PropertyChanged;
     internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
   }
 
   public class Data : INotifyPropertyChanged
   {
     private float _hourlyFloat;
     public float HourlyFloat
     {
       get => this._hourlyFloat;
       set { this._hourlyFloat = value; OnPropertyChanged(); }
     }
 
     public event PropertyChangedEventHandler PropertyChanged;
     internal void OnPropertyChanged([CallerMemberName] string propName = "") =>
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
   }
 
   public class EnforceNumericConvert : IValueConverter
   {
     public object Convert(object value, Type targetType, object parameter, string language)
     {
       return value.ToString();
     }
 
     public object ConvertBack(object value, Type targetType, object parameter, string language)
     {
       float par = 0;
       float.TryParse(value.ToString(), out par);
       return par;
     }
   }
 }
· Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RodFalanga avatar image
0 Votes"
RodFalanga answered ·

@PeterFleischer-3316 I do have this in my page's XAML:

<Page.DataContext> <vm:MainPageViewModel x:Name="ViewModel" /> </Page.DataContext>

In your example you have

 public ViewModel ViewModel { get; } = new ViewModel();

in your page's constructor. Do you find that to be better than what I've done?

· 3 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, I don't know what you did since you didn't show any code. I do not know your further conditions and I can not say which is better.

0 Votes 0 · ·
RodFalanga avatar image RodFalanga PeterFleischer-3316 ·

Here's additional XAML from MainWindow:

<Page x:Class="SalaryConversion.Views.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"; xmlns:Core="using:Microsoft.Xaml.Interactions.Core" xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:controls="using:Template10.Controls" xmlns:converters="using:SalaryConversion.ValueConverters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"; xmlns:local="using:SalaryConversion.Views" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"; xmlns:vm="using:SalaryConversion.ViewModels" mc:Ignorable="d">

 <Page.DataContext>
     <vm:MainPageViewModel x:Name="ViewModel" />
 </Page.DataContext>
0 Votes 0 · ·

Hi, both of these usages can achieve Binding, their actual difference lies in x: bind and binding. First the datacontext of x:bind is current page, it will find the property in the current Code-Bebind class. But you need to set DataContext explicitly for Binding. And the default mode of x:bind is oneTime, it means it will change the value one time. In addition, x:bind generates source code at compile-time, the binding will take effect at runtime, so x:bind is more faster. For more details about their difference, you can refer to this document.

1 Vote 1 · ·