简体   繁体   English

RelativeSource 不使用子属性工作

[英]RelativeSource not working using child property

I do not understand the issue / difference with the first binding with these examples:我不明白这些示例与第一个绑定的问题/区别:

(CustomTheme, ItemFormatting and FontNormal are DependencyObjects) (CustomTheme、ItemFormatting 和 FontNormal 是 DependencyObjects)

This one gets the error further down:这个错误进一步下降:

          NullToDependencyPropertyUnsetConverter unsetconv = new NullToDependencyPropertyUnsetConverter();

            Binding binding = new Binding("CustomTheme.ItemFormatting.FontNormal")
            {
                Converter = unsetconv,
                RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ThemableUserControl), 2)
            };
            BindingOperations.SetBinding(itemsample.ItemFormatting, ItemFormatting.FontNormalProperty, binding);

This is an absolute equivalent of the first one and works:这绝对等同于第一个并且有效:

     Binding binding = new Binding("CustomTheme.ItemFormatting.FontNormal")
            {
                Converter = unsetconv,
                Source = tucMain
            };
            BindingOperations.SetBinding(itemsample.ItemFormatting, ItemFormatting.FontNormalProperty, binding);

This is not what I want to achieve but works:这不是我想要实现的,但有效:

            Binding binding1 = new Binding("CustomTheme.ItemFormatting")
            {
                Converter = unsetconv,
                RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ThemableUserControl), 2)
            };
            BindingOperations.SetBinding(itemsample, uc_item.ItemFormattingProperty, binding1);

I do not understand why I am getting the this output error on the first one:我不明白为什么我在第一个错误上得到这个 output 错误:

System.Windows.Data Error: 4: Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='AddonInterface.ThemableUserControl', AncestorLevel='2''. System.Windows.Data 错误:4:找不到与引用'RelativeSource FindAncestor,AncestorType ='AddonInterface.ThemableUserControl',AncestorLevel ='2''的绑定源。 BindingExpression:Path=CustomTheme.ItemFormatting.FontNormal; BindingExpression:Path=CustomTheme.ItemFormatting.FontNormal; DataItem=null;数据项=空; target element is 'ItemFormatting' (HashCode=43532274);目标元素是“ItemFormatting”(HashCode=43532274); target property is 'FontNormal' (type 'Font')目标属性是“FontNormal”(类型“字体”)

This is the window xaml.这是 window xaml。

<Window
        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"
        xmlns:local="clr-namespace:TestApp"
        xmlns:UIControls="clr-namespace:AddonInterface.UIControls;assembly=AddonInterface" xmlns:AddonInterface="clr-namespace:AddonInterface;assembly=AddonInterface"
    xmlns:uielements="clr-namespace:AddonInterface.UIElements;assembly=AddonInterface"
    xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding" x:Class="TestApp.SubthemeWidgetItem"
        mc:Ignorable="d" x:Name="this"
        Title="MainWindow" Height="579.722" Width="1040.889" Loaded="This_Loaded" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    
    >
    <Window.Resources>
        <ResourceDictionary Source="pack://application:,,,/AddonInterface;component/Themes/defaultMainStyle.xaml"/>

    </Window.Resources>

    <AddonInterface:ThemableUserControl Name="tucMain" >
        <StackPanel>
            <AddonInterface:ThemableUserControl Name="tucSub" Height="225" Margin="0,0,604,0">
                <DockPanel Margin="0,0,-18,-41">


                    <Label Height="33">x) tuc2</Label>
                    <AddonInterface:AddonUserControl Name="aucSub" Margin="0,0,0,155" Width="147">
                        <DockPanel>
                            <Label Height="33">x) auc</Label>

                            <AddonInterface:uc_item  Name="itemsample" Title="x) item " />
                        </DockPanel>


                    </AddonInterface:AddonUserControl>


                </DockPanel>

            </AddonInterface:ThemableUserControl>


            <CheckBox IsChecked="True" Name="cbx2" FontSize="20" FontWeight="Bold">Toptheme</CheckBox>
            <UIControls:uc_themedesigner Visibility="{c:Binding ElementName=cbx2,Path=IsChecked}"  Name="mainwindowtheme"   />
            <CheckBox IsChecked="True" Name="cbx1" FontSize="20" FontWeight="Bold">Subtheme</CheckBox>
            <UIControls:uc_themedesigner Visibility="{c:Binding ElementName=cbx1,Path=IsChecked}" AllowNulls="True" Name="customtheme"    ></UIControls:uc_themedesigner>
            <Button Content="Button" Click="Button_Click_1"/>





        </StackPanel>

    </AddonInterface:ThemableUserControl>



</Window>

Code behind:后面的代码:

using AddonInterface;
using AddonInterface.DependencyObjects;
using AddonInterface.themes;
using AddonInterface.UIControls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class SubthemeWidgetItem : Window
    {
        public SubthemeWidgetItem()
        {



            InitializeComponent();

            tucMain.CustomTheme = new dm_theme();
            tucMain.CustomTheme.ApplyAllDefault();
            tucMain.CustomTheme.ItemFormatting.FontNormal = new Font() { Size=60}; 
            tucSub.CustomTheme = new dm_theme();



            //BINDINGS THEME DESIGNER / TUC THEME
            mainwindowtheme.SetBinding(uc_themedesigner.ThemeDMProperty, new Binding("CustomTheme") { Source = tucMain });
            customtheme.SetBinding(uc_themedesigner.ThemeDMProperty, new Binding("CustomTheme") { Source = aucSub });


        

            this.Loaded += (a, b) =>
            {




                NullToDependencyPropertyUnsetConverter unsetconv = new NullToDependencyPropertyUnsetConverter();

                //Binding binding = new Binding("CustomTheme.ItemFormatting.FontNormal")
                //{
                //    Converter = unsetconv,
                //    RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ThemableUserControl), 2)
                //};
                //BindingOperations.SetBinding(itemsample.ItemFormatting, ItemFormatting.FontNormalProperty, binding);



                Binding binding = new Binding("CustomTheme.ItemFormatting.FontNormal")
                {
                    Converter = unsetconv,
                    Source = tucMain
                };
                BindingOperations.SetBinding(itemsample.ItemFormatting, ItemFormatting.FontNormalProperty, binding);



                //Binding binding1 = new Binding("CustomTheme.ItemFormatting")
                //{
                //    Converter = unsetconv,
                //    RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ThemableUserControl), 2)
                //};
                //BindingOperations.SetBinding(itemsample, uc_item.ItemFormattingProperty, binding1);




            };

            TestBorder = new dm_border() { Background = Brushes.Orange };

            this.DataContext = this;
        }





        public dm_border TestBorder
        {
            get { return (dm_border)GetValue(TestBorderProperty); }
            set
            {
                SetValue(TestBorderProperty, value);


            }
        }


        public static readonly DependencyProperty TestBorderProperty =
         DependencyProperty.Register("TestBorder", typeof(dm_border), typeof(SubthemeWidgetItem),
     new FrameworkPropertyMetadata(default(dm_border),
         FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
         new PropertyChangedCallback(OnTestBorderPropertyChanged)));


        private static void OnTestBorderPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            SubthemeWidgetItem uci = sender as SubthemeWidgetItem;
            if (uci != null)
            {
                uci.OnTestBorderChanged();
            }
        }


        private void OnTestBorderChanged()
        {


        }




    }
}

thanks Have a nice day谢谢祝你有美好的一天

The first binding is wrong, as the target object is itemSample .第一个绑定是错误的,因为目标 object 是itemSample itemsample.ItemFormatting is a property on itemSample and not an element of the visual tree. itemsample.ItemFormattingitemSample的属性,而不是可视树的元素。 That's why RelativeSource can't be resolved by the XAML parser.这就是 XAML 解析器无法解析RelativeSource的原因。

To make the RelativeSource binding using the same source as your second code version, you must change the Binding.Path .要使用与第二个代码版本相同的源进行RelativeSource绑定,您必须更改Binding.Path

Note that setting a binding on a nested property is not possible using BindingOperations .请注意,无法使用BindingOperations在嵌套属性上设置绑定。 The binding must be set directly on the object that owns the target property.绑定必须直接在拥有目标属性的 object 上设置。 You can use FrameworkElement.SetBinding for this purpose.您可以为此目的使用FrameworkElement.SetBinding

The final binding would become:最终的绑定将变为:

C# C#

var unsetConv = new NullToDependencyPropertyUnsetConverter();

var binding = new Binding("CustomTheme.ItemFormatting.FontNormal")
{
  Converter = unsetConv,
  RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ThemableUserControl), 2)
};

itemSample.ItemFormatting.SetBinding(ItemFormatting.FontNormalProperty, binding);

XAML XAML

<Window.Resources>
  <NullToDependencyPropertyUnsetConverter x:Key="NullToDependencyPropertyUnsetConverter" />
</Window.Resources>

<AddonInterface:uc_item  Name="ItemSample" 
                         ItemFormatting="{Binding RelativeSource={RelativeSource AncestorType=ThemableUserControl, AncestorLevel=2}, 
                                                  Path=CustomTheme.ItemFormatting, 
                                                  Converter={StaticResource NullToDependencyPropertyUnsetConverter}}" />

Since you are using a named element as the binding source, you can also use the Binding.ElementName property instead:由于您使用命名元素作为绑定源,因此您也可以使用Binding.ElementName属性:

<AddonInterface:uc_item  Name="ItemSample" 
                         ItemFormatting="{Binding Elementname=tucMain, 
                                                  Path=CustomTheme.ItemFormatting, 
                                                  Converter={StaticResource NullToDependencyPropertyUnsetConverter}}" />

I have ended up using an extension method getParent<> to find the themableusercontrol ancestor and setting it as source.我最终使用了扩展方法 getParent<> 来查找 theableusercontrol 祖先并将其设置为源。

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

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