Issues with ContentDialog and x:Bind

I have a ContentDialog that implements INotifyPropertyChanged. I have a TextBox with its Text property bound via x:Bind syntax to a string property on my code-behind.

If I edit the contents of the TextBox, and then click on another control in the ContentDialog (losing focus on the TextBox), and then click on the primary button, by the time I get to the primary button click event handler the text property has been updated with the content of the TextBox control = PERFECT.

However, if I change the contents of the TextBox but then keep it in focus and THEN click on the primary button the binding never gets updated.

It seems that the reason for this is because the built-in buttons in ContentDialog do not acquire focus before their click eventhandlers are fired, and as x:Bind only supports LostFocus binding, these bindings will never be updated.

I'm staggered that this big bug exists. So my 2 questions are

1) Is there a workaround

2) Do I have to abandon x:Bind and use WPF-style Binding syntax, where I can change the UpdateSourceTrigger within the binding itself.

I'm hoping that another UWP dev has come across this and knows of a work around

EDIT

Ive created some example code to demonstrate the issue.

page:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Button Content="Open" Click="OpenClick" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Page>

code behind:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OpenClick(object sender, RoutedEventArgs e)
    {
        var dialog = new ContentDialog1();
        await dialog.ShowAsync();
    }
}

content dialog:

<ContentDialog
    x:Class="App1.ContentDialog1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="TITLE"
    PrimaryButtonText="Button1"
    PrimaryButtonClick="ContentDialog_PrimaryButtonClick">

    <Grid>
        <TextBox Text="{x:Bind Path=TestText, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="100"/>
    </Grid>
</ContentDialog>

content dialog code behind:

public sealed partial class ContentDialog1 : ContentDialog, INotifyPropertyChanged
{
    public ContentDialog1()
    {
        InitializeComponent();
    }

    private string _testText;
    public string TestText
    {
        get => _testText;
        set
        {
            _testText = value;
            OnPropertyChanged(nameof(TestText));
        }
    }

    private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
    {
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

And my target sdk verions are:

If you click open the content dialog, enter some text, then click the primary button - if you have a breakpoint in the click handler you'll see that the binding hasn't updated with your entered text

I can't reproduce the issue: the setter of string property in code-behind is always fired before the ContentDialog_PrimaryButtonClick, even if I click the primary button while the focus is still on the TextBox. My sample (tested on Fall Creators Update):

MyContentDialog.xaml

<Grid>
    <TextBox Text="{x:Bind MyString, Mode=TwoWay}"/>
</Grid>

MyContentDialog.xaml.cs

public sealed partial class MyContentDialog : ContentDialog, INotifyPropertyChanged
{
    private DTO dto;

    private string myString;
    public string MyString
    {
        get
        {
            return myString;
        }
        set
        {
            myString = value;
            NotifyPropertyChanged(nameof(MyString));
        }
    }

    public MyContentDialog(DTO dto)
    {
        this.InitializeComponent();

        this.dto = dto;
        MyString = dto.text;
    }


    private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
    {
        dto.text = MyString;
    }

    private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
    {
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

DTO.cs

public class DTO
{
    public string text;
}

MainPage.xaml.cs

private async void Page_Loaded(object sender, RoutedEventArgs e)
{
    DTO dto = new DTO { text = "My text" };

    MyContentDialog dialog = new MyContentDialog(dto);
    await dialog.ShowAsync();

    await new MessageDialog("My text, after being edited by the user in MyContentDialog: " + dto.text).ShowAsync();
}

Could you share your code? What's the min and target version of your project?

Issues with ContentDialog and x:Bind - xaml - html, I have a ContentDialog that implements INotifyPropertyChanged. I have a TextBox with its Text property bound via x:Bind syntax to a string property on my� It seems that the reason for this is because the built-in buttons in ContentDialog do not acquire focus before their click eventhandlers are fired, and as x:Bind only supports LostFocus binding, these bindings will never be updated.

OK, I've looked into this, and have tested this on all SDK's back to build 10586. Essentially ContentDialog is broken for x:Bind bindings to TextBox, because TextBox is required to lose focus in order for its bindings to update. I have tried a number of hacks including walking the visual tree on Loaded to add extra handlers to the hidden buttons, and trying to force them to focus (thus removing focus from any TextBox, and triggering the binding update) before the click handler fires, but without UWP supporting the tunnelling event strategy (like WPF), it is not possible to inject any kind of event handling between the button press and the hard-wired click handler running. The upshot is that x:Bind (which doesn't support UpdateSourceTrigger other than LostFocus) cannot reliably work in ContentDialog with TextBox controls.

I have logged a bug at Microsoft uservoice.

The only way to solve this is to abandon x:Bind and use classic Bindings which support an UpdateSourceTrigger of PropertyChanged - thus allowing bindings to be always up-to-date before the button in clicked. But even this is a hack, because UpdateSourceTrigger of PropertyChanged will cause unnecessary updates in your setters - which can be problematic. Also updating setters in INotifyPropertyChanged will fire many additional rounds of the arrange/measure pass for all of your layout.

The only real solution is to write your own ContentDialog control. I was tempted to do this, but without access to Microsofts source code for these controls, it's difficult to know if you have done it successfully

Crashing App with Unhandled Exception after Rendering Content , have an ObservableCollection that I fill with BitmapImages. Once filled I open up a content dialog with a listview and item template with the� Note For general info about using data binding in your app with {x:Bind} (and for an all-up comparison between {x:Bind} and {Binding}), see Data binding in depth. The {x:Bind} markup extension—new for Windows 10—is an alternative to {Binding}. {x:Bind} runs in less time and less memory than {Binding} and supports better debugging.

I just figured it out I spent a lot of time just like you did almost two days failed and Content Dialog crashes my application if there is null object binding to any of the control have to use Converters.

I was just thinking how about placing a usercontrol on the dialog and see if the binding works.

Let me try post the results here.

If you have figured out any other way of doing this let me know

WindowsXamlHost TextBox in ContentDialog Ignores characters , Closed. aquinn39 opened this issue on Nov 26, 2019 � 11 comments. Closed < ContentDialog x:Name="KeyRemapDialog" Title="Remap a key"� Labels 65 Milestones 0 New issue Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

[UWP] x:Bind event handling and MVVM - MSDN, In "classic" binding I used Interactions SDK to bind commands to When I handle the SelectionChanged event with x:Bind, my as Answer" the responses that resolved your issue, and to click "Unmark as An event handler for a button in a ContentDialog. public void SaveChanges(ContentDialog sender,� I have created a new Contentdialog in Visual Studio 2015 in Windows insider build 14393 using the latest SDK. In my dialog, I have the following code: &lt;ContentDialog x:Class=&quot;App.EditMultip

ContentDialog ignoring CanExecute - Microsoft Q&A, The issue with this is that by the time you press the button, the dialog So you can use TemplateBinding to bind PrimaryButtonCommand with Command. Resources>; <Style TargetType="ContentDialog" x:Key="MyStyle">� The new x:Bind syntax in XAML for Windows 10 UWP provides a compile type check; improving my confidence that I'm headed down the right path as I build the view. I was surprised to learn that x:Bind constrains the output of the sample data in the Design tab of Blend or Visual Studio 2015.

Windows 10 XAML Tips: MessageDialog and ContentDialog , The ContentDialog class was introduced in Windows Phone 8.1 xmlns:x="http ://schemas.microsoft.com/winfx/2006/xaml" The MaxWidth property must be set to avoid problems with wide content on small devices. You will still have to databind the checkbox to the IsPrimaryButtonEnabled property. Note. The x:Bind value also lets the editor know about the data type, so you can use IntelliSense instead of typing in the property name in an x:Bind expression. Try it on the code you just pasted in: place the cursor just after x:Bind and press the Spacebar to see a list of properties you can bind to.

Comments
  • Thanks for your help. Have created a version of my code that exhibits this issue, and included target SDK info