Why isn't the Hourly property being set?

Rod Falanga 561 Reputation points
2020-03-07T16:09:42.917+00:00

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?

Universal Windows Platform (UWP)
{count} votes

4 answers

Sort by: Most helpful
  1. Xiaodi Yan 876 Reputation points MVP
    2020-03-07T23:35:52.173+00:00

    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://learn.microsoft.com/en-us/windows/uwp/data-binding/function-bindings


  2. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-03-28T09:02:47.553+00:00

    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. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-12T06:45:53.947+00:00

    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;
        }
      }
    }
    
    0 comments No comments

  4. Rod Falanga 561 Reputation points
    2020-04-12T15:01:53.357+00:00

    anonymous user-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?