简体   繁体   English

WPF:绑定仅在使用 Snoop 时有效

[英]WPF : Binding only working when using Snoop

We use a Custom Popup in our WPF application.我们在 WPF 应用程序中使用自定义弹出窗口。 The problem with the WPF native popup is that: WPF 本机弹出窗口的问题在于:

  • It use a new Windown so the content end up in an other visual tree which make transform calculation more complicated and you have no control over the Zindex.它使用了一个新的 Windown,因此内容最终会出现在另一个可视化树中,这使得转换计算更加复杂,并且您无法控制 Zindex。 it will always be on top of the rest.它永远是最重要的。
  • The content loose the DataContext and all the Inherited properties or resources.内容丢失了 DataContext 和所有继承的属性或资源。

The difference of our custom popup with the native WPF Popup is that it put the Content of the popup is put in a container in the same window instead of putting it in a new windows.我们的自定义弹出窗口与原生 WPF 弹出窗口的不同之处在于,它将弹出窗口的内容放在同一窗口的容器中,而不是放在新窗口中。 And the content is a logical child of the popup.并且内容是弹出窗口的逻辑孩子。 So it solve the native popup problems with DataContext and DP inheritance.所以它解决了DataContext和DP继承的原生弹出问题。

Our Popup work like the native one in XAML我们的 Popup 像 XAML 中的原生一样工作

<pop:UbiPopup IsOpen="{Binding ElementName=pop_button,Path=IsChecked,Mode=TwoWay}" PlacementTarget="{Binding ElementName=maingrid}" Placement="CenterHorizontal,Top" >
    <Border Background="Blue" BorderThickness="0"  Margin="5">
           <TextBlock Text="{Binding Label}"
    </Border>
 </pop:UbiPopup>

But there is a bug with Bindings.但是绑定有一个错误。 When a Binding is done in the Content of the Popup, the binding will not work.当在弹出窗口的内容中完成绑定时,绑定将不起作用。 But if we use Snoop ( https://github.com/snoopwpf/snoopwpf ) and check the object, the Binding sudenly work.但是,如果我们使用 Snoop ( https://github.com/snoopwpf/snoopwpf ) 并检查对象,则 Binding 会突然起作用。 It does this for every kind of binding, using datacontext or elementname.它使用 datacontext 或 elementname 为每种绑定执行此操作。

Internaly, when snoop display the list of DP of an objet, if it find a binding for some reason it remove it and put it back again.在内部,当 snoop 显示对象的 DP 列表时,如果它由于某种原因找到绑定,则将其删除并重新放回。 So we come up with this rather ugly hack to make bindings work.所以我们想出了这个相当丑陋的 hack 来使绑定工作。 When the popup content is loaded, we walk along all visual child, get all their DP by reflection, and if it has a binding, we remove it and put it back again 🤮当弹出内容加载完毕后,我们沿着所有的visual child,通过反射获取他们所有的DP,如果有绑定,我们将其移除并重新放回🤮

Warning : Ugly Code警告:丑陋的代码

//Binding don't work inside UbiPopup. They work if they are snooped.
//So we simulate Snoop. we check every DP of every visual children of the Popup and we re-set the Binding if one is found.
foreach (var obj in WpfHelper.ChildrenEnumerator(container))
{
    var props = obj.GetType().GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy)
    .Where((f) => f.FieldType.Equals(typeof(DependencyProperty)))
    .Select((f) => f.GetValue(null) as DependencyProperty);
    foreach (var p in props)
    {
        var bd = BindingOperations.GetBindingBase(obj, p);
        if (bd != null)
        {
            BindingOperations.SetBinding(obj, p, bd);
        }
    }
}

Does anyone know where this problem can com from and how to solve it in a cleaner way有谁知道这个问题可能来自哪里以及如何以更清洁的方式解决它

Snoop does not remove and re-apply bindings. Snoop 不会删除和重新应用绑定。 What it does is create new bindings which bind to the DependencyProperties of the objects/controls which causes your bindings to be evaluated again.它所做的是创建新的绑定,绑定到对象/控件的 DependencyProperties,这会导致再次评估您的绑定。

You wrote that you are adding the content to the logical tree, if you do that by calling AddLogicalChild you should also overwrite the LogicalChildren property to return the content.您写道,您正在将内容添加到逻辑树,如果您通过调用 AddLogicalChild 来做到这一点,您还应该覆盖 LogicalChildren 属性以返回内容。

Hope that solves your issue.希望能解决您的问题。

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

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