I do not understand the issue / difference with the first binding with these examples:
(CustomTheme, ItemFormatting and FontNormal are 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:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='AddonInterface.ThemableUserControl', AncestorLevel='2''. BindingExpression:Path=CustomTheme.ItemFormatting.FontNormal; DataItem=null; target element is 'ItemFormatting' (HashCode=43532274); target property is 'FontNormal' (type 'Font')
This is the 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
.itemsample.ItemFormatting
is a property onitemSample
and not an element of the visual tree. That's whyRelativeSource
can't be resolved by the XAML parser.To make the
RelativeSource
binding using the same source as your second code version, you must change theBinding.Path
.Note that setting a binding on a nested property is not possible using
BindingOperations
. The binding must be set directly on the object that owns the target property. You can useFrameworkElement.SetBinding
for this purpose.The final binding would become:
C#
XAML
Since you are using a named element as the binding source, you can also use the
Binding.ElementName
property instead: