Why isn't the Hourly property being set?

Rod Falanga 571 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,331 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,331 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 571 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?


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.