question

BitSmithy-4663 avatar image
0 Votes"
BitSmithy-4663 asked ·

How to trigger converter programatically

Hello,


I have TextBox binded to other UIElement property. The TextBox shows value of this property.

         Windows.UI.Xaml.Data.Binding bc1 = new Windows.UI.Xaml.Data.Binding() { Path = new PropertyPath("Width") };
         bc1.Mode = BindingMode.TwoWay;
         bc1.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
         tbx.SetBinding(TextBox.TextProperty, bc1);

         bc1.Converter = new MeasureUnitsConverter();


I want to trigger MeasureUnitsConverter() converter in ComboBox event SelectionChanged

         <ComboBox x:Name="cmb"                           
                   ItemsSource="{x:Bind MeasureUnitsList}"
                   SelectedIndex="0"
                   SelectionChanged="cmb_SelectionChanged"
                   ></ComboBox>


How to do such task?

windows-uwp
· 1
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.

Does @PeterFleischer-3316 's new answer solve your issue?

0 Votes 0 ·
danielescipioni avatar image
0 Votes"
danielescipioni answered ·

Lookin at your code, in my opinion, using the Converter is not the right approach when the ComboBox selection changes. It is ok when the Width changes, but for the unit of measure I would do this:

Change the converter in this way, this is to have a common code usable by the converter and by code behind:

public class MeasureUnitsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return Convert(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        //From TextBox to UIElement (From string to double)

        /* Under construction
            if (value == null)
                return 0;
            else if (mu == "epx")
                return value;
            else if (mu == "inch")
                return (double)value * 96;
            else if (mu == "mm")
                return (double)value * 96 * 24.5;
        else
        */
        return value;
    }

    public static string Convert(object value)
    {
        //From UIElement to TextBox (from double to string)
        if (value == null)
            return "0.00";
        else if (mu == "epx")
            return value.ToString(); //epx
        else if (mu == "inch")
            return ((double)value / 96).ToString(); //epx
        else if (mu == "mm")
            return ((double)value / 96 * 25.4).ToString(); //epx
        else
            return value.ToString();
    }
}

then change cmb_SelectionChanged in this way

private void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (sender is ComboBox cmb)
    {
        if (rect == null) return;
        mu = cmb.SelectedValue.ToString();
        tbx.Text = MeasureUnitsConverter.Convert(rect.Width);
    }
}

·
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.

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

Hi, raise PropertyChanged:

 : INotifyPropertyChanged
   {
 ...
     private void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
       OnPropChanged(nameof(Width));
     }
    
     public event PropertyChangedEventHandler PropertyChanged;
     protected void OnPropChanged([CallerMemberName] string propertyName = "") =>
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
· 1 ·
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 failed to implement your idea. Probably I do something wrong. I attach my full code.

7957-measureunits.txt


0 Votes 0 ·
measureunits.txt (3.0 KiB)
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi, your problem is DataContext of tbx. In following demo I change DataContext and binding to other property.

 <Page
     x:Class="Change_MeasureUnit_Test.MainPage"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="using:Change_MeasureUnit_Test"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   <StackPanel>
     <TextBox x:Name="tbx"/>
     <ComboBox x:Name="cmb" ItemsSource="{Binding MeasurmentUnitsList}"/>
   </StackPanel>
 </Page>
    
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Data;
    
 namespace Change_MeasureUnit_Test
 {
   public sealed partial class MainPage : Page, INotifyPropertyChanged
   {
     public static string[] MeasurmentUnits = { "epx", "mm", "inch" };
     public List<string> MeasurmentUnitsList
     { get { return MeasurmentUnits.ToList(); } }
    
     public static string mu = "epx";
    
     public MainPage()
     {
       this.InitializeComponent();
    
       this.DataContext = this;  <------------------------
    
       //tbx.DataContext = rect; //rect is Shapes.Rectangle defined in MainPage.xaml  <-----------------
    
       Binding bc1 = new Binding() { Path = new PropertyPath("WidthValue") };  <---------------------
    
       bc1.Converter = new MeasureUnitsConverter();
    
       bc1.Mode = BindingMode.TwoWay;
       bc1.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
       tbx.SetBinding(TextBox.TextProperty, bc1);
    
       cmb.SelectionChanged += cmb_SelectionChanged;
    
       tbx.LostFocus += tbx_LostFocus;
     }
    
     public double WidthValue { get; set; } = 100;  <-------------------------------------

     private void cmb_SelectionChanged(object sender, SelectionChangedEventArgs e)
     {
       if (sender is ComboBox cmb)
       {
         mu = cmb.SelectedValue.ToString();
         OnPropChanged(nameof(WidthValue));  <---------------------------
       }
     }
    
     public event PropertyChangedEventHandler PropertyChanged;
     private void OnPropChanged([CallerMemberName] string propertyName = "") =>
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
     private void tbx_LostFocus(object sender, RoutedEventArgs e)
     {
       BindingExpression cbe = tbx.GetBindingExpression(TextBox.TextProperty);
       cbe.UpdateSource();
     }
    
    
     public class MeasureUnitsConverter : IValueConverter
     {
       public object Convert(object value, Type targetType, object parameter, string language)
       {
         //From UIElement to TextBox (from double to string)
         if (value == null)
           return 0.00;
         else if (mu == "epx")
           return value; //epx
         else if (mu == "inch")
           return (double)value / 96; //epx
         else if (mu == "mm")
           return (double)value / 96 * 25.4;//epx
         else
           return value;
       }
    
       public object ConvertBack(object value, Type targetType, object parameter, string language)
       {
         //From TextBox to UIElement (From string to double)
    
         /* Under construction
             if (value == null)
                 return 0;
             else if (mu == "epx")
                 return value;
             else if (mu == "inch")
                 return (double)value * 96;
             else if (mu == "mm")
                 return (double)value * 96 * 24.5;
         else
         */
         return value;
       }
     }
   }
 } 
·
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.