2017-08-29 60 views
1

TreeView的資源中,我有一個HierarchicalDataTemplate也定義了上下文菜單樣式。目標是能夠以編程方式將MenuItem指定爲圖標名稱作爲其Tag,然後讓前端顯示正確的圖標。僅在檢查時出現WPF上下文菜單數據綁定圖標

<StackPanel.ContextMenu> 
    <ContextMenu ItemsSource="{Binding MenuItems}"> 
     <ContextMenu.Resources> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Icon"> 
        <Setter.Value> 
         <local:StringToIcon IconName="{Binding Tag, RelativeSource={RelativeSource AncestorType=MenuItem}}" /> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ContextMenu.Resources> 
    </ContextMenu> 
</StackPanel.ContextMenu> 

StringToIcon是另一種控制,對於測試,看起來就像這樣。它由依賴屬性IconName支持。

<UserControl x:Class="MyApp.Components.StringToIcon" 
      ... 
      Name="StringIconControl"> 
    <Image DataContext="{Binding ElementName=StringIconControl}"> 
     <Image.Style> 
      <Style TargetType="{x:Type Image}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IconName}" Value="Refresh"> 
         <Setter Property="Source" Value="{StaticResource IconRefresh}"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Image.Style> 
    </Image> 
</UserControl> 

IconRefresh簡直是一個全球可用的資源:

<BitmapImage x:Shared="False" x:Key="IconRefresh" UriSource="pack://application:,,,/Resources/Icons/refresh.png" /> 

當啓動應用程序,沒有上下文菜單刷新圖標出現。他們都是空白的。我得到綁定錯誤,我帶領相信是由於上下文菜單可視化樹不是:

無法爲參照結合找到源「的RelativeSource FindAncestor,AncestorType =」 System.Windows.Controls .MenuItem',AncestorLevel ='1''。 BindingExpression:路徑=標籤;的DataItem = NULL;目標元素是'StringToIcon'(Name ='StringIconControl');目標屬性是'IconName'(類型'String')

但是,當使用Snoop檢查菜單時,所有的綁定和依賴項屬性都是正確的。以這種方式檢查後,檢查到的刷新圖標奇蹟般地出現,好像它迫使綁定重新評估一樣。您可以逐個執行此操作,以顯示此圖標的每個實例。

如何解決這個似乎在這裏發生的惰性綁定?或者還有其他什麼玩法?我看到另一篇文章,建議將菜單數據上下文附加到可視樹中的,但我沒有看到在這種情況下會出現什麼內容。

回答

0

最終的解決方案,結合問題是使一個新的類來保存菜單項目的詳情:

public class BindableMenuItem 
{ 
    public BindableMenuItem(string name, ICommand command) 
    { 
     this.Name = name; 
     this.Command = command; 
    } 
    public string Name { get; set; } 
    public ICommand Command { get; set; } 
    public string IconName { get; set; } 
    public ObservableCollection<BindableMenuItem> Children { get; set; } 
} 

然後將其捆綁起來,以菜單項的樣式如下:

<Style TargetType="MenuItem"> 
    <Setter Property="Header" Value="{Binding Name}" /> 
    <Setter Property="Command" Value="{Binding Command}" /> 
    <Setter Property="ItemsSource" Value="{Binding Children}" /> 
    <Setter Property="Icon"> 
     <Setter.Value> 
      <local:StringToIcon IconName="{Binding IconName}" /> 
     </Setter.Value> 
    </Setter> 
</Style> 

大概這是有效的,因爲綁定不依賴於在可視樹中存在相對源,而是它有一個具體的模型類來使用。

但是,上述關於多樣式實例仍然存在問題。我會爲此發佈另一個問題。