我在構造函數中初始化屬性時遇到了控件模板內數據綁定問題。如果屬性在構造函數中初始化,XAML綁定似乎不會設置
這裏是展示情況(你也可以下載sample solution):
CustomControl1.cs
public class CustomControl1 : ContentControl
{
static CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(CustomControl1),
new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
public CustomControl1()
{
Content = "Initial"; // comment this line out and everything
// will start working just great
}
}
CustomControl1風格:
<Style TargetType="{x:Type local:CustomControl1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CustomControl2.cs:
public class CustomControl2 : ContentControl
{
static CustomControl2()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(CustomControl2),
new FrameworkPropertyMetadata(typeof(CustomControl2)));
}
}
CustomControl風格:
<Style TargetType="{x:Type local:CustomControl2}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl2}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<local:CustomControl1
Content="{Binding Content,
RelativeSource={RelativeSource
AncestorType=local:CustomControl2}}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Window1.xaml:
<Window x:Class="WpfApplication5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:local="clr-namespace:WpfApplication5">
<Grid>
<local:CustomControl2 Content="Some content" />
</Grid>
</Window>
所以,問題是:當你啓動應用程序,這是由設置CustomControl1的內容似乎是 「初始」構造函數,而不是「Some content」字符串,它應該通過綁定來設置。
當我們從構造函數中刪除初始化時,綁定開始工作。首先,讓我預測答案:「您應該在其元數據中設置依賴項屬性的初始值:無論是在註冊時還是通過元數據重寫功能」。 Yeap,你說得對,但這種初始化方法的問題在於屬性是集合類型的,所以如果我提供new MyCustomCollection()
作爲屬性的默認值,那麼CustomControl1
的每個實例將共享該集合的相同實例這顯然不是主意。
我已經做了的問題的一些調試,這裏的結果:
- 結合實例被創建,當我們把它放在元素的語法和分配
x:Name
它,那麼它是通過Template.FindName("PART_Binding", this)
訪問裏面有OnApplyTemplate
。 - 綁定只是沒有設置屬性:在同一
OnApplyTemplate
代碼this.GetBindingExpression(ContentProperty)
返回null
。 - 綁定本身沒有任何問題:在
OnApplyTemplate
裏面我們可以查看它,然後我們可以簡單地將它設置爲這樣的屬性:this.SetBinding(ContentProperty, myBinding)
- 一切都會正常工作。
任何人都可以解釋如何以及爲什麼發生?
有沒有人有解決方案設置依賴項屬性的非共享初始值,所以綁定不會中斷?
在此先感謝!
UPD: 最奇怪的是,與最高跟蹤級別調試輸出是這兩種情況下是相同的:要麼當沒有發生,或者如果它的約束力。
這裏有雲:
System.Windows.Data Warning: 52 : Created BindingExpression (hash=18961937) for Binding (hash=44419000)
System.Windows.Data Warning: 54 : Path: 'Content'
System.Windows.Data Warning: 56 : BindingExpression (hash=18961937): Default mode resolved to OneWay
System.Windows.Data Warning: 57 : BindingExpression (hash=18961937): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 58 : BindingExpression (hash=18961937): Attach to WpfApplication5.CustomControl1.Content (hash=47980820)
System.Windows.Data Warning: 62 : BindingExpression (hash=18961937): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 61 : BindingExpression (hash=18961937): Resolve source deferred
System.Windows.Data Warning: 63 : BindingExpression (hash=18961937): Resolving source
System.Windows.Data Warning: 66 : BindingExpression (hash=18961937): Found data context element: <null> (OK)
System.Windows.Data Warning: 69 : Lookup ancestor of type CustomControl2: queried Border (hash=11653293)
System.Windows.Data Warning: 69 : Lookup ancestor of type CustomControl2: queried CustomControl2 (hash=54636159)
System.Windows.Data Warning: 68 : RelativeSource.FindAncestor found CustomControl2 (hash=54636159)
System.Windows.Data Warning: 74 : BindingExpression (hash=18961937): Activate with root item CustomControl2 (hash=54636159)
System.Windows.Data Warning: 104 : BindingExpression (hash=18961937): At level 0 - for CustomControl2.Content found accessor DependencyProperty(Content)
System.Windows.Data Warning: 100 : BindingExpression (hash=18961937): Replace item at level 0 with CustomControl2 (hash=54636159), using accessor DependencyProperty(Content)
System.Windows.Data Warning: 97 : BindingExpression (hash=18961937): GetValue at level 0 from CustomControl2 (hash=54636159) using DependencyProperty(Content): 'Some content'
System.Windows.Data Warning: 76 : BindingExpression (hash=18961937): TransferValue - got raw value 'Some content'
System.Windows.Data Warning: 85 : BindingExpression (hash=18961937): TransferValue - using final value 'Some content'
UPD2:增加了一個鏈接到sample solution
由於還有第二個答案(第一個被作者刪除),他們甚至沒有遠程匹配問題,所以我用粗體突出顯示了我的問題。請確保你得到**問題**必需品,並確保你正在回答**問題**。 – archimed7592