简体   繁体   English

x:在UWP中绑定(通用Windows平台)

[英]x:Bind in UWP (Universal Windows Platform)

Right. 对。 So moving from WPF to UWP, I'm trying to use x:Bind to get compile-time benefits. 所以从WPF转到UWP,我正在尝试使用x:Bind来获得编译时的好处。 Simple scenarios work fine; 简单的场景工作正常; however I have found a number of issues that I was not able to solve. 但是我发现了一些我无法解决的问题。 They are all related, so I thought I'd post them in one place: 它们都是相关的,所以我想我会把它们放在一个地方:

  1. I haven't been able to make Intellisense work with x:Bind . 我无法让Intellisense与x:Bind I have set DataContext (as well as d:DataContext just as we do in WPF) both in XAML and in the constructor, but it won't show members no matter what. 我在XAML和构造函数中都设置了DataContext(以及d:DataContext就像在WPF中一样),但无论如何都不会显示成员。 Has anyone done this successfully? 有人做过这个吗?
  2. Then I read somewhere that in UWP, DataContext is always set to Page 's code-behind (really??) and that I need to define a ViewModel type property in the code-behind and then use that property in x:Bind . 然后我在某处读到,在UWP中, DataContext始终设置为Page的代码隐藏(真的??),我需要在代码隐藏中定义一个ViewModel类型属性,然后在x:Bind使用该属性。 Is this correct? 这个对吗? I tried it and it works but gives rise to the next question. 我尝试了它并且它有效但引起了下一个问题。
  3. If I define a property of ViewModel type in Page's code-behind, Any sub-properties that raise PropertyChanged notifications do not update the UI. 如果我在Page的代码隐藏中定义了ViewModel类型的属性,那么引发PropertyChanged通知的任何子属性都不会更新UI。 For example, if the code-behind property is named Game (of type GameVM ) and there is a public property in GameVM named Player (of type GamePlayer ), and in turn GamePlayer contains a property named Name , the x:Bind path will look like {x:Bind Path=Game.Player.Name} . 例如,如果代码隐藏属性名为Game (类型GameVM ),有一个公共财产GameVM命名的Player (类型GamePlayer ),反过来GamePlayer包含一个名为属性Name ,在x:Bind路径看起来喜欢{x:Bind Path=Game.Player.Name} But if I do this, any change notifications raised from within Name property do not update Page's UI. 但是,如果我这样做,从Name属性中引发的任何更改通知都不会更新Page的UI。

One alternate I tried was to listen to PropertyChanged at each level and then bubble it up the hierarchy, but that hasn't worked. 我试过的一个替代方案是在每个级别监听PropertyChanged,然后在层次结构中冒泡,但这没有用。 Even if it does, doing this seems a bit too much work. 即使它确实如此,这样做似乎有点太多了。 In WPF sub-properties like Game.Player.Name work properly without having to doing property change bubbling. 在像Game.Player.Name这样的WPF子属性中,无需进行属性更改冒泡Game.Player.Name正常工作。 Or am I missing something? 或者我错过了什么?

Right. 对。 After playing with it for a few days and searching numerous references, here are my findings: 在玩了几天并搜索了大量的参考资料后,我的发现如下:

  1. {x:Bind} lacks design-time support. {x:Bind}缺乏设计时支持。 The feature is on the wishlist though. 该功能虽然在愿望清单上 You may want to upvote it there. 你可能想在那里投票。 (The new version of Visual Studio 15.4.4 does support Intellisense in {x:Bind}in the required way.) (新版本的Visual Studio 15.4.4以所需方式支持{x:Bind}中的Intellisense。)
  2. {x:Bind} uses code-behind as its DataContext. {x:Bind}使用代码隐藏作为其DataContext。 So you need to define a public property of your ViewModel type in the code-behind and then use it in your {x:Bind} path. 因此,您需要在代码隐藏中定义ViewModel类型的公共属性,然后在{x:Bind}路径中使用它。
  3. As pointed out by IInspectable, the default mode for {x:Bind} is OneTime , unlike {Binding} which uses OneWay or TwoWay in almost all cases. 正如IInspectable所指出的, {x:Bind}的默认模式是OneTime ,不像{Binding}几乎在所有情况下都使用OneWayTwoWay So you need to explicitly specify Mode in your binding. 因此,您需要在绑定中明确指定Mode People coming from WPF should take special care of it. 来自WPF的人应该特别注意它。
  4. Sub-properties that implement notification change work perfectly fine in {x:Bind} . 实现通知更改的子属性在{x:Bind}完全正常工作。 There is no need of bubbling these notifications upwards in the property hierarchy. 无需在属性层次结构中向上冒泡这些通知。 The problem I was facing (#3 in the question) was because my sub-property was of type List<T> . 我面临的问题(问题中的#3)是因为我的子属性是List<T>类型。 I changed it to ObservableCollection<T> and it started working. 我将其更改为ObservableCollection<T>并开始工作。

Hope this works somebody down the road. 希望这能让人有所作为。

Well as a beginner, the only question I can answer for you is the first one. 作为初学者,我能回答的唯一问题是第一个问题。 Intellisense does not work inside the {x:Bind}. Intellisense在{x:Bind}内部不起作用。 The members are never shown there in UWP for some unknown reasons. 由于某些未知原因,UWP中的成员永远不会出现在那里。 As for the next two questions of yours, I am still working on them. 至于你的下两个问题,我仍然在研究它们。

I ran into the same challenge that you have seen. 我遇到了你所看到的同样的挑战。 In my experience, in order to create the compile-time binding and have it update with custom objects as properties, the Page class seems to need to know about the data context and custom objects... all you need to do is reference them in the code behind, and then bind to them in the XAML. 根据我的经验,为了创建编译时绑定并使用自定义对象作为属性进行更新,Page类似乎需要了解数据上下文自定义对象...您需要做的就是引用它们后面的代码,然后在XAML中绑定它们。 This creates the code generation objects it needs. 这将创建它需要的代码生成对象。

For example, I have a viewmodel, CustomerViewModel that is bound in XAML. 例如,我有一个viewModel,CustomerViewModel绑定在XAML中。 That viewmodel also has a property of type IGuest. 该viewmodel还具有IGuest类型的属性。 In order to use the guest object and have it update properly, I came up with this in the code behind... 为了使用guest对象并让它正确更新,我在后面的代码中提出了这个...

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

You don't need to assign any of the UI data contexts from the code behind... simply reference the datacontext that is bound in XAML. 您不需要从后面的代码中分配任何UI数据上下文...只需引用XAML中绑定的datacontext。 When binding to any straight viewmodel properties, I use {x:Bind Path=vm.IsEditing, Mode=OneWay }. 绑定到任何直接viewmodel属性时,我使用{x:Bind Path=vm.IsEditing, Mode=OneWay }。 For binding to any of the guest properties, it looks like this, {x:Bind Path=g.FirstName, Mode=TwoWay}. 对于绑定到任何guest属性,它看起来像这样, {x:Bind Path=g.FirstName, Mode=TwoWay}. You could do something like this for your Player object. 你可以为你的Player对象做这样的事情。

I have run into times where x:Bind simply won't do what I expect it to do no matter what I try. 我遇到了x:无论我尝试什么,绑定根本不会做我期望它做的事情。 This can usually be solved by breaking things out into smaller user controls with more specific data contexts or by using "regular" Binding. 这通常可以通过将事物分解为具有更具体数据上下文的较小用户控件或使用“常规”绑定来解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM