2017-01-23 72 views
0

我有一個簡單的附加依賴項屬性應該提供一個鼠標顏色爲我的自定義控件:命名空間的問題:附加依賴找不到屬性

public class Ext 
{ 
    public static readonly DependencyProperty HighlightBrushProperty = DependencyProperty.RegisterAttached("HighlightBrush", typeof(Brush), typeof(Ext), new PropertyMetadata(default(Brush))); 

    public static void SetHighlightBrush(DependencyObject element, Brush value) 
    { 
     element.SetValue(HighlightBrushProperty, value); 
    } 

    public static Brush GetHighlightBrush(DependencyObject element) 
    { 
     return (Brush) element.GetValue(HighlightBrushProperty); 
    } 
} 

我使用它像這樣在我Generic.xaml

<Style TargetType="{x:Type local:MyButton}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type Button}"> 
       <Border x:Name="Border" 
         Background="{TemplateBinding Background}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         BorderThickness="{TemplateBinding BorderThickness}"> 
        <ContentPresenter /> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsMouseOver" Value="True"> 
         <Setter TargetName="Border" Property="Background" Value="{Binding (local:Ext.HighlightBrush), RelativeSource={RelativeSource TemplatedParent}}" /> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

但現在我必須在客戶端使用相同的命名空間:

<Window ... 
     xmlns:local="clr-namespace:Eval.Wpf.AttachedProperty.Controls;assembly=Eval.Wpf.AttachedProperty.Controls"> 
    <StackPanel> 
     <local:MyButton Background="LightGray" local:Ext.HighlightBrush="DarkOrange" Content=" - Press me - " /> 
    </StackPanel> 
</Window> 

了變化克命名空間別的東西,像<c:MyButton Background="LightGray" c:Ext.HighlightBrush="DarkOrange" Content=" - Press me - " />

System.Windows.Data Error: 40 : BindingExpression path error: '(local:Ext.HighlightBrush)' property not found on 'object' ''MyButton' (Name='')'. BindingExpression:Path=(local:Ext.HighlightBrush); DataItem='MyButton' (Name=''); target element is 'Border' (Name='Border'); target property is 'Background' (type 'Brush') 

爲什麼的使用附加屬性不是類型安全的結束了?我該如何解決這個問題?

+1

我記得在某些情況下'{Binding(local:MyClass.MyProperty)}'語法不起作用。現在解決我的問題是明確使用'Binding.Path'屬性,即'{Binding Path =(local:MyClass.MyProperty)}'來代替。雖然你的問題與命名空間前綴有關,但這很奇怪,所以它可能是完全不同的東西。 – Grx70

+0

@ Grx70是的。這是解決方案。你應該發佈它。你有什麼想法是什麼原因?設置/省略'Path ='表達式有什麼區別? – Marcel

回答

1

解決方案

正如我在評論中提及,你的情況的解決方案是明確使用Binding.Path屬性,即:

{Binding Path=(local:Ext.HighlightBrush), ...} 

診斷

我真的不知道是什麼是這種行爲背後的原因,但我已經做了一些測試,並將分享結果和觀察結果。

的一切都在這裏首先是說明(從WindowXAML定義節選)發行的簡要例如:

<Window.Resources> 
    <ControlTemplate x:Key="T1" xmlns:foo="clr-namespace:FooBar"> 
     <TextBlock Text="{Binding (foo:MainWindow.Test), 
            RelativeSource={RelativeSource TemplatedParent}}" /> 
    </ControlTemplate> 
</Window.Resources> 
<Grid xmlns:bar="clr-namespace:FooBar"> 
    <Control x:Name="C1" bar:MainWindow.Test="test" Template="{StaticResource T1}" /> 
</Grid> 

我們結束了以下消息綁定錯誤:

System.Windows.Data Error: 40 : BindingExpression path error: 
    '(foo:MainWindow.Test)' property not found on 'object' ''Control' (Name='C1')'. 
    BindingExpression:Path=(foo:MainWindow.Test); 
    DataItem='Control' (Name='C1'); 
    target element is 'TextBlock' (Name=''); 
    target property is 'Text' (type 'String') 

當然,如果我們使用Binding.Path屬性,所有東西都可以正常工作。

現在,如果我們的結合,我們可以看到在輸出(關鍵的,在我看來)差設置PresentationTraceSource.TraceLevel="High" - 在第一種情況下,我們得到

System.Windows.Data Warning: 58 : Path: '(foo:MainWindow.Test)' 

但在後一種情況下,我們得到

System.Windows.Data Warning: 58 : Path: '(0)' 

如此看來,使用第一種語法等效於

new PropertyPath("(foo:MainWindow.Test)") 
實例化路徑

(我認爲它是由new Binding("(foo:MainWindow.Test)")構造函數重載完成),但第二個好像使用PathProperty構造函數的另一重載:

new PropertyPath("(0)", MainWindow.TestProperty) 

免責聲明 什麼,我接下來要說的只有我的假設,所以它可能只是錯誤的。

它看起來像"(foo:MainWindow.Test)"路徑被視爲一個CLR訪問器,只有當有可用的綁定來源時才解析。在這種情況下,源是C1控件。該框架足夠聰明,可以知道該控件的哪個部分已定義,因此它會嘗試使用該上下文解析附加屬性。但在我們的情況下,foo前綴在該上下文中沒有定義,因此解析失敗,因此綁定失敗。這似乎證實,假設一個看法是,如果你定義所述前綴,即使在控制自身:

<Control x:Name="C1" xmlns:foo="clr-namespace:FooBar" (...) /> 

的結合開始正常工作。此外,如果我們修改我們的模板:

<ControlTemplate x:Key="T1"> 
    <TextBlock Text="{Binding (bar:MainWindow.Test), 
           RelativeSource={RelativeSource TemplatedParent}}" /> 
</ControlTemplate> 

即使bar前綴在此背景下undefined,並且XAML設計師抱怨它,它仍然確實在運行工作。

第二種方法工作的原因是該屬性在實例化Binding時解析 - 必須在此時解決該問題才能傳遞給PropertyPath構造函數。並且由於BindingXAML的上下文中定義了foo前綴,因此解析成功並且一切正常。

總之,似乎這兩種情況下通過該框架將嘗試解析(foo:MainWindow.Test)字符串實際屬性的時間只剩不同,但是,不僅差異,它是區別