ContentDialog和x的问题:绑定

时间:2017-12-30 16:44:09

标签: xaml uwp uwp-xaml

我有一个ContentDialog来实现INotifyPropertyChanged。我有一个TextBox,其Text属性通过x:Bind语法绑定到我的代码隐藏后的字符串属性。

如果我编辑TextBox的内容,然后点击ContentDialog中的另一个控件(失去对TextBox的关注),然后点击主按钮,按当我到达主按钮单击事件处理程序时,text属性已使用TextBox control = PERFECT的内容进行更新。

但是,如果我更改TextBox的内容但是保持焦点,然后点击主按钮,绑定永远不会更新。

这似乎是因为ContentDialog中的内置按钮在点击事件处理程序被触发之前没有获得焦点,并且x:Bind仅支持LostFocus绑定,这些绑定永远不会更新。

我错开了这个大错误的存在。所以我的两个问题是

1)是否有解决方法

2)我是否必须放弃x:Bind并使用WPF风格的Binding语法,我可以在其中更改绑定本身内的UpdateSourceTrigger

我希望另一个UWP开发者遇到过这个并知道一项工作

修改

我已经创建了一些示例代码来演示这个问题。

页:

<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>
代码背后的代码:

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

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

内容对话框:

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

内容对话框代码:

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));
    }
}

我的目标sdk版本是:

enter image description here

如果您单击打开内容对话框,请输入一些文本,然后单击主按钮 - 如果您在点击处理程序中有断点,您将看到绑定未使用您输入的文本进行更新< / p>

3 个答案:

答案 0 :(得分:0)

我无法重现这个问题:代码隐藏中的string属性的setter始终在ContentDialog_PrimaryButtonClick之前被触发,即使我在焦点仍在{时单击主按钮时也是如此{1}}。我的样本(在Fall Creators Update上测试):

MyContentDialog.xaml

TextBox

MyContentDialog.xaml.cs

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

DTO.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));
    }
}

MainPage.xaml.cs中

public class DTO
{
    public string text;
}

你可以分享你的代码吗?什么是项目的最小和目标版本?

答案 1 :(得分:0)

好的,我已经对此进行了调查,并在所有SDK上对此进行了测试,以构建10586.基本上ContentDialogx:Bind绑定到TextBox而被破坏,因为{{1}需要失去焦点才能使其绑定更新。 我尝试了很多黑客攻击,包括在TextBox上移动可视树,为隐藏按钮添加额外的处理程序,并尝试强制它们聚焦(从而从任何Loaded移除焦点,并触发绑定更新)在点击处理程序触发之前,但如果没有UWP支持隧道事件策略(如WPF),则无法在按下按钮和运行的硬连线点击处理程序之间注入任何类型的事件处理。 结果是TextBox(不支持x:Bind以外的UpdateSourceTrigger)无法在LostFocus ContentDialog控件中可靠地工作。

我在Microsoft uservoice上记录了一个错误。

解决此问题的唯一方法是放弃TextBox并使用支持x:Bind UpdateSourceTrigger的经典绑定 - 从而允许绑定在按钮之前始终保持最新状态点击。 但即使这是一个黑客攻击,因为PropertyChanged UpdateSourceTrigger会导致你的setter不必要的更新 - 这可能会有问题。同时更新PropertyChanged中的setter也会为您的所有布局启动许多额外的安排/测量通道。

唯一真正的解决方案是编写自己的INotifyPropertyChanged控件。我很想做到这一点,但是如果没有访问这些控件的微软源代码,很难知道你是否成功完成了它

答案 2 :(得分:0)

我刚刚发现我花了很多时间,就像您将近两天都失败了一样,如果将空对象绑定到任何控件,则必须使用Converters,Content Dialog会使我的应用程序崩溃。

我只是在考虑如何在对话框上放置一个用户控件,看看绑定是否起作用。

让我尝试在此处发布结果。

如果您已经找到其他方法,请告诉我