【问题标题】:x:Bind in UWP (Universal Windows Platform)x:在 UWP(通用 Windows 平台)中绑定
【发布时间】:2017-02-01 03:33:09
【问题描述】:

没错。所以从 WPF 转移到 UWP,我试图使用 x:Bind 来获得编译时的好处。简单的场景工作正常;但是我发现了一些我无法解决的问题。它们都是相关的,所以我想我会将它们发布在一个地方:

  1. 我无法让 Intellisense 与 x:Bind 一起工作。我在 XAML 和构造函数中都设置了 DataContext(以及 d:DataContext,就像我们在 WPF 中所做的那样),但无论如何它都不会显示成员。有没有人成功做到这一点?
  2. 然后我在某处读到,在 UWP 中,DataContext 始终设置为 Page 的代码隐藏(真的吗??),我需要在代码隐藏中定义一个 ViewModel 类型属性,然后使用它x:Bind 中的财产。它是否正确?我试过了,它有效,但引发了下一个问题。
  3. 如果我在 Page 的代码隐藏中定义 ViewModel 类型的属性,任何引发 PropertyChanged 通知的子属性都不会更新 UI。例如,如果代码隐藏属性被命名为GameGameVM 类型)并且GameVM 中有一个名为PlayerGamePlayer 类型)的公共属性,而GamePlayer 又包含一个名为Name 的属性,x:Bind 路径将类似于{x:Bind Path=Game.Player.Name}。但是,如果我这样做,从 Name 属性中引发的任何更改通知都不会更新 Page 的 UI。

我尝试过的另一种方法是在每个级别收听 PropertyChanged,然后将其向上冒泡,但这并没有奏效。即使确实如此,这样做似乎也有点太多工作了。在 WPF 中,Game.Player.Name 等子属性可以正常工作,而无需进行属性更改冒泡。还是我错过了什么?

【问题讨论】:

  • 第一点:在获得建议之前,您总是需要构建项目。我总是构建项目,然后打开属性窗口,然后从可能的资源列表中选择绑定源
  • @MatthiasHerrmann:这不是问题所在。我已经多次构建了该项目。请阅读我在下面 Monish 的回答中的讨论。
  • {x:Bind} 的默认模式是OneTime。在大多数情况下,{Binding} 的默认值为 OneWay。相关问答:With compiled bindings (x:bind), why do I have to call Bindings.Update()?.
  • @IInspectable:哎呀。那会造成严重破坏。让我读。

标签: c# xaml mvvm uwp


【解决方案1】:

作为一个初学者,我唯一能回答的就是第一个问题。 Intellisense 在 {x:Bind} 内不起作用。由于某些未知原因,成员从未出现在 UWP 中。至于你接下来的两个问题,我还在研究中。

【讨论】:

  • 关于这方面的任何官方文字或其他参考资料(智能感知)?
  • 您所说的部分内容不正确。 Intellisense 与{Binding} 配合良好。当我在 UWP 中使用 {Binding} 时,我可以在 XAML 中看到我的 VM 成员。只有{x:Bind} 缺少智能感知。您提供的链接仅涉及x:Bind
  • 好的。现在看起来好多了,尽管那不是我想听到的:)。无论如何,我认为我现在可以在没有 Intellisense 的情况下生活。不过,其他两个问题更为重要。
【解决方案2】:

我遇到了与您所见相同的挑战。根据我的经验,为了创建编译时绑定并使用自定义对象作为属性进行更新,Page 类似乎需要了解数据上下文自定义对象...您需要做的就是在后面的代码中引用它们,然后在 XAML 中绑定到它们。这将创建它需要的代码生成对象。

例如,我有一个在 XAML 中绑定的视图模型 CustomerViewModel。该视图模型还具有 IGuest 类型的属性。为了使用来宾对象并使其正确更新,我在后面的代码中提出了这个...

        CustomerViewModel vm
        {
            get
            {
                return (CustomerViewModel)DataContext;
            }
        }
      IGuest g
        {
            get
            {
                return vm.CurrentGuest;
            }
        }
        public CartGuestControl()
        {
            this.InitializeComponent();
        }

您不需要从后面的代码中分配任何 UI 数据上下文...只需引用绑定在 XAML 中的数据上下文即可。当绑定到任何直接视图模型属性时,我使用{x:Bind Path=vm.IsEditing, Mode=OneWay}。对于绑定到任何来宾属性,它看起来像这样,{x:Bind Path=g.FirstName, Mode=TwoWay}. 你可以为你的 Player 对象做这样的事情。

我遇到过这样的情况:无论我尝试什么,x:Bind 都不会按照我的预期去做。这通常可以通过将事物分解为具有更具体数据上下文的较小用户控件或使用“常规”绑定来解决。

【讨论】:

  • 感谢分享信息。如果您仔细查看您的建议,您的x:Bind 仍在使用代码隐藏类作为其DataContext。您所做的只是在代码隐藏中创建顶级属性,这些属性充当这些嵌套对象属性的包装器。这正是我最终所做的(问题的最后一段),但当时这对我不起作用。我现在找到了这个问题的根本原因。完成挖掘后,我会发布我的发现。
【解决方案3】:

没错。在玩了几天并搜索了许多参考资料后,这是我的发现:

  1. {x:Bind} 缺乏设计时支持。该功能在wishlist 上。你可能想在那里投票。 (新版 Visual Studio 15.4.4 确实以需要的方式支持 {x:Bind} 中的 Intellisense。)
  2. {x:Bind} 使用代码隐藏作为其 DataContext。因此,您需要在代码隐藏中定义 ViewModel 类型的公共属性,然后在 {x:Bind} 路径中使用它。
  3. 正如 IInspectable 所指出的,{x:Bind} 的默认模式是 OneTime,不像 {Binding} 在几乎所有情况下都使用 OneWayTwoWay。因此,您需要在绑定中明确指定 Mode。来自 WPF 的人应该特别注意它。
  4. 实现通知更改的子属性在{x:Bind} 中工作得非常好。无需在属性层次结构中向上冒泡这些通知。我面临的问题(问题中的#3)是因为我的子属性是List<T> 类型。我将其更改为ObservableCollection<T>,它开始工作了。

希望这对未来的人有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2016-04-25
    • 1970-01-01
    • 2016-10-02
    • 2016-07-29
    • 2016-01-09
    • 1970-01-01
    相关资源
    最近更新 更多