4
votes

I'm trying to set my textbox text binding inside a flyout, but my viewmodel's setter for the bound property is never called. I have the view setup like this:

<CommandBar>
   <AppBarButton Icon="Edit" AllowFocusOnInteraction="true">
      <Flyout>
         <StackPanel>
            <TextBlock Text="Enter Qty:" />
            <TextBox Text="{Binding EditQty, Mode=TwoWay}" InputScope="Number" />
            <Button Content="Update" Command="{Binding EditCommand}" />
         </StackPanel>
      </Flyout>
<CommandBar>

My viewmodel code is also simple:

public decimal _editQty;
public decimal EditQty
{
    get => _editQty;
    set => Set(ref _editQty, value);
}

I've even tried to use UpdateSourceTrigger=Explicit with the binding, and then in the button's click event, setup the codebehind to call

textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

During debugging I can see the textBox.Text value has changed correctly, but the setter still isn't called by UpdateSource(). I'm using Windows 10 Build 14393 (Anniversary Edition) if that matters.

Is there a way to do this? At this point I will have to scrap the idea and put the textbox in a dialog, even though having it in the flyout would be a better user experience.

2
Is the getter being called at startup? - Sean O'Neil
The getter is called when the flyout opens. - Rkand

2 Answers

4
votes

According to Microsoft, UWP has been unable to do TwoWay bindings to decimal since the WinRT days! (Reason being: Don't Ask!) Their solution is to use float.

If you really need to bind to decimal, it seems you can manually convert with an IValueConveter (Thanks to Stephan Olson whose solution was linked to the answer):

public class DecimalConverter: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)
    {
        return decimal.Parse(value as string);
    }
}

My binding now looks like this:

<TextBox Text="{Binding EditQty, Mode=TwoWay, Converter={StaticResource DecimalConverter}}" InputScope="Number" />
1
votes

Sometimes this happens when dealing with popups/controls that have an alternate visual tree. Some properties don't cascade. Whenever this happens to me, I use a TextBlock to print the type of the DataContext:

<CommandBar>
   <AppBarButton Icon="Edit" AllowFocusOnInteraction="true">
      <Flyout>
         <StackPanel>
            <TextBlock Text="{Binding}" /> <!-- This will print typeof DataContext -->

            <TextBlock Text="Enter Qty:" />
            <TextBox Text="{Binding EditQty, Mode=TwoWay}" InputScope="Number" />
            <Button Content="Update" Command="{Binding EditCommand}" />
         </StackPanel>
      </Flyout>
<CommandBar>

If that TextBlock prints empty, then you know DataContext is not making it down to your Flyout.