WPF: привязка работает только при использовании Snoop - PullRequest
1 голос
/ 26 февраля 2020

Мы используем Custom Popup в нашем приложении WPF. Проблема с собственным всплывающим окном WPF состоит в том, что:

  • В нем используется новый Windown, поэтому содержимое попадает в другое визуальное дерево, что усложняет вычисление преобразования и у вас нет контроля над Zindex. оно всегда будет поверх остальных.
  • Содержимое теряет DataContext и все унаследованные свойства или ресурсы.

Разница в нашем настраиваемом всплывающем окне с собственным WPF Popup заключается в что он помещает содержимое всплывающего окна, помещается в контейнер в том же окне вместо того, чтобы помещать его в новый windows. И контент является логическим потомком всплывающего окна. Таким образом, это решает собственные проблемы всплывающих окон с DataContext и DP наследования

Наш 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>

Но в Bindings есть ошибка. Когда привязка выполняется в содержимом всплывающего окна, привязка не будет работать. Но если мы используем Sn oop (https://github.com/snoopwpf/snoopwpf) и проверяем объект, связывание неожиданно сработает. Он делает это для каждого вида привязки, используя datacontext или elementname.

Внутренне, когда sn oop отображает список DP объекта, если по какой-то причине он находит привязку, он удаляет ее и помещает ее вернуться снова. Поэтому мы придумали этот довольно уродливый хак, чтобы заставить работать привязки. Когда всплывающее содержимое загружено, мы проходим по всем визуальным дочерним элементам, получаем все их DP по отражению, и, если оно имеет привязку, мы удаляем его и снова помещаем обратно ?

Предупреждение: уродливый код

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

Кто-нибудь знает, откуда может возникнуть эта проблема и как ее решить более чистым способом

1 Ответ

0 голосов
/ 30 марта 2020

Sn oop не удаляет и повторно не применяет привязки. Он создает новые привязки, которые связывают свойства DependencyProperties объектов / элементов управления, что приводит к повторной оценке ваших привязок.

Вы писали, что добавляете контент в логическое дерево, если вы делаете это с помощью вызывая AddLogicalChild, вы также должны перезаписать свойство LogicalChildren, чтобы вернуть содержимое.

Надеюсь, что это решит вашу проблему.

...